From e17a1eefb521a1e68f91c85410f75e418379678d Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sat, 7 Feb 2015 06:35:28 +0000 Subject: [PATCH] - initial version git-svn-id: http://moon:8086/svn/vhdl/trunk@1073 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/ChangeLog | 3570 ++++++++ .../ieee/add/numeric_std_additions.vhdl | 2640 ++++++ .../ieee/add/numeric_std_unsigned_c.vhdl | 1891 ++++ .../ieee/add/standard_additions_c.vhd | 1685 ++++ .../ieee/add/standard_textio_additions_c.vhd | 1417 +++ .../ieee/add/std_logic_1164_additions.vhd | 2681 ++++++ lib/Standard/ieee/math_complex.vhd | 1087 +++ lib/Standard/ieee/math_complex_body.vhd | 1604 ++++ lib/Standard/ieee/math_real.vhd | 628 ++ lib/Standard/ieee/math_real_body.vhd | 1941 ++++ lib/Standard/ieee/new/math_complex.vhdl | 126 + lib/Standard/ieee/new/math_real.vhdl | 211 + lib/Standard/ieee/new/numeric_bit.vhdl | 813 ++ lib/Standard/ieee/new/numeric_std.vhdl | 853 ++ lib/Standard/ieee/new/standard.vhdl | 133 + lib/Standard/ieee/new/std_logic_1164.vhdl | 178 + lib/Standard/ieee/new/std_logic_arith_ex.vhdl | 217 + .../ieee/new/std_logic_arith_syn.vhdl | 192 + lib/Standard/ieee/new/std_logic_signed.vhdl | 83 + lib/Standard/ieee/new/std_logic_textio.vhdl | 73 + lib/Standard/ieee/new/std_logic_unsigned.vhdl | 79 + lib/Standard/ieee/new/textio.vhd | 86 + lib/Standard/ieee/numeric_bit.vhdl | 813 ++ lib/Standard/ieee/numeric_bit_body.vhd | 2573 ++++++ lib/Standard/ieee/numeric_std.vhdl | 853 ++ lib/Standard/ieee/numeric_std_body.vhd | 2671 ++++++ lib/Standard/ieee/old/numeric_bit.vhd | 2573 ++++++ lib/Standard/ieee/old/numeric_std.vhd | 2671 ++++++ lib/Standard/ieee/std_logic_1164.vhdl | 178 + lib/Standard/ieee/std_logic_1164_body.vhd | 1384 +++ lib/Standard/ieee/std_logic_arith_ex.vhd | 2088 +++++ lib/Standard/ieee/std_logic_arith_ex.vhdl | 217 + lib/Standard/ieee/std_logic_arith_syn.vhd | 2391 +++++ lib/Standard/ieee/std_logic_arith_syn.vhdl | 192 + lib/Standard/ieee/std_logic_signed.vhdl | 83 + lib/Standard/ieee/std_logic_signed_body.vhd | 343 + lib/Standard/ieee/std_logic_textio.vhdl | 73 + lib/Standard/ieee/std_logic_textio_body.vhd | 634 ++ lib/Standard/ieee/std_logic_unsigned.vhdl | 79 + lib/Standard/ieee/std_logic_unsigned_body.vhd | 329 + lib/Standard/ieee_proposed/fixed_pkg_c.vhd | 7846 +++++++++++++++++ lib/Standard/ieee_proposed/float_pkg_c.vhd | 6133 +++++++++++++ lib/Standard/std/textio.vhdl | 130 + lib/Standard/std/textio_body.vhdl | 1326 +++ lib/Standard/synopsys/std_logic_arith.vhd | 2399 +++++ lib/Standard/synopsys/std_logic_misc.vhd | 966 ++ lib/Standard/synopsys/std_logic_signed.vhd | 343 + lib/Standard/synopsys/std_logic_textio.vhd | 654 ++ lib/Standard/synopsys/std_logic_unsigned.vhd | 329 + lib/doc/Fixed_ug.pdf | Bin 0 -> 80675 bytes lib/doc/Float_ug.pdf | Bin 0 -> 86772 bytes lib/netlists/cpu.ngc | 3 + lib/netlists/cpu_V4.ngc | 3 + lib/netlists/mips_top.ngc.R1 | 3 + lib/netlists/mips_top.ngc.R9 | 3 + lib/netlists/mips_top_20090124.ngc | 3 + lib/netlists/mips_top_20130208.ngc | 3 + 57 files changed, 62477 insertions(+) create mode 100644 lib/ChangeLog create mode 100644 lib/Standard/ieee/add/numeric_std_additions.vhdl create mode 100644 lib/Standard/ieee/add/numeric_std_unsigned_c.vhdl create mode 100644 lib/Standard/ieee/add/standard_additions_c.vhd create mode 100644 lib/Standard/ieee/add/standard_textio_additions_c.vhd create mode 100644 lib/Standard/ieee/add/std_logic_1164_additions.vhd create mode 100644 lib/Standard/ieee/math_complex.vhd create mode 100644 lib/Standard/ieee/math_complex_body.vhd create mode 100644 lib/Standard/ieee/math_real.vhd create mode 100644 lib/Standard/ieee/math_real_body.vhd create mode 100644 lib/Standard/ieee/new/math_complex.vhdl create mode 100644 lib/Standard/ieee/new/math_real.vhdl create mode 100644 lib/Standard/ieee/new/numeric_bit.vhdl create mode 100644 lib/Standard/ieee/new/numeric_std.vhdl create mode 100644 lib/Standard/ieee/new/standard.vhdl create mode 100644 lib/Standard/ieee/new/std_logic_1164.vhdl create mode 100644 lib/Standard/ieee/new/std_logic_arith_ex.vhdl create mode 100644 lib/Standard/ieee/new/std_logic_arith_syn.vhdl create mode 100644 lib/Standard/ieee/new/std_logic_signed.vhdl create mode 100644 lib/Standard/ieee/new/std_logic_textio.vhdl create mode 100644 lib/Standard/ieee/new/std_logic_unsigned.vhdl create mode 100644 lib/Standard/ieee/new/textio.vhd create mode 100644 lib/Standard/ieee/numeric_bit.vhdl create mode 100644 lib/Standard/ieee/numeric_bit_body.vhd create mode 100644 lib/Standard/ieee/numeric_std.vhdl create mode 100644 lib/Standard/ieee/numeric_std_body.vhd create mode 100644 lib/Standard/ieee/old/numeric_bit.vhd create mode 100644 lib/Standard/ieee/old/numeric_std.vhd create mode 100644 lib/Standard/ieee/std_logic_1164.vhdl create mode 100644 lib/Standard/ieee/std_logic_1164_body.vhd create mode 100644 lib/Standard/ieee/std_logic_arith_ex.vhd create mode 100644 lib/Standard/ieee/std_logic_arith_ex.vhdl create mode 100644 lib/Standard/ieee/std_logic_arith_syn.vhd create mode 100644 lib/Standard/ieee/std_logic_arith_syn.vhdl create mode 100644 lib/Standard/ieee/std_logic_signed.vhdl create mode 100644 lib/Standard/ieee/std_logic_signed_body.vhd create mode 100644 lib/Standard/ieee/std_logic_textio.vhdl create mode 100644 lib/Standard/ieee/std_logic_textio_body.vhd create mode 100644 lib/Standard/ieee/std_logic_unsigned.vhdl create mode 100644 lib/Standard/ieee/std_logic_unsigned_body.vhd create mode 100644 lib/Standard/ieee_proposed/fixed_pkg_c.vhd create mode 100644 lib/Standard/ieee_proposed/float_pkg_c.vhd create mode 100644 lib/Standard/std/textio.vhdl create mode 100644 lib/Standard/std/textio_body.vhdl create mode 100644 lib/Standard/synopsys/std_logic_arith.vhd create mode 100644 lib/Standard/synopsys/std_logic_misc.vhd create mode 100644 lib/Standard/synopsys/std_logic_signed.vhd create mode 100644 lib/Standard/synopsys/std_logic_textio.vhd create mode 100644 lib/Standard/synopsys/std_logic_unsigned.vhd create mode 100644 lib/doc/Fixed_ug.pdf create mode 100644 lib/doc/Float_ug.pdf create mode 100644 lib/netlists/cpu.ngc create mode 100644 lib/netlists/cpu_V4.ngc create mode 100644 lib/netlists/mips_top.ngc.R1 create mode 100644 lib/netlists/mips_top.ngc.R9 create mode 100644 lib/netlists/mips_top_20090124.ngc create mode 100644 lib/netlists/mips_top_20130208.ngc diff --git a/lib/ChangeLog b/lib/ChangeLog new file mode 100644 index 0000000..b529498 --- /dev/null +++ b/lib/ChangeLog @@ -0,0 +1,3570 @@ +2010-03-13 Jens + * misc/flash_port_wb.vhd 1.2: + - made time specs in nano seconds, thus independent of clock + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/flash_port_wb.vhd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-03-12 Jens + * CPUs/MIPS/dist/files.dist 1.7: + * CPUs/MIPS/dist/mdist 1.13: + * CPUs/MIPS/dist/tmpl/mips_sys.vhd 1.6: + * CPUs/MIPS/dist/tmpl/notes.txt 1.11: + * CPUs/MIPS/doc/J-MIPS.txt 1.7: + - Back to current work + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * PCK_FIO-1.16/PCK_FIO.vhd 1.2: + * radio/ddc/sim/tb_results.m 1.6: + Minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/files.dist 1.6: + * CPUs/MIPS/dist/mdist 1.12: + * CPUs/MIPS/dist/tmpl/mips_sys.vhd 1.5: + * CPUs/MIPS/dist/tmpl/notes.txt 1.10: + * CPUs/MIPS/doc/J-MIPS.txt 1.6: + - Roll back for Release 12 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * radio/ddc/src/syn_ddc.vhd 1.9: + * radio/ddc/src/tb_ddc.vhd 1.8: + - added Altera stuff + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/JCpu/sim/tb_cpu_itest.wdo 1.2: + * CPUs/MIPS/dist/mdist 1.14: + * CPUs/MIPS/dist/mdist 1.15: + * CPUs/MIPS/dist/mdist 1.16: + * CPUs/MIPS/dist/tmpl/notes.txt 1.12: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-03-11 Jens + * CPUs/MIPS/src/core/mips_dcache.vhd 1.20: + - improved instant_raw logic. Less false alarms + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.16: + - added asynchronous BUS FIFOs + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/files.dist 1.5: + * CPUs/MIPS/dist/mdist 1.11: + * CPUs/MIPS/dist/tmpl/notes.txt 1.9: + * CPUs/MIPS/doc/J-MIPS.txt 1.5: + * CPUs/MIPS/syn/ise101/mips_top.prj 1.5: + * CPUs/MIPS/syn/ise101/mips_top_vhdl.prj 1.5: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/mips_sys.vhd 1.4: + Minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/tb_mips_top.vhd 1.2: + * CPUs/MIPS/dist/tmpl/tb_mips_top.wdo 1.3: + deleted + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/tb_mips_sys.vhd 1.1: + * CPUs/MIPS/dist/tmpl/tb_mips_sys.wdo 1.1: + * CPUs/MIPS/doc/toolchain/howto_build.txt 1.1: + * CPUs/MIPS/doc/toolchain/make.sh 1.1: + * CPUs/MIPS/doc/toolchain/newlib-1.16.0-jens.patch 1.1: + * CPUs/MIPS/doc/toolchain/newlib-1.17.0-jens.patch 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-03-07 Jens + * CPUs/MIPS/src/tb_mips_top.vhd 1.23: + * uart/uart_wb.vhd 1.10: + - added generic 'simulate_tx' for output of TX-Data into simulation log + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.28: + * CPUs/MIPS/src/core/mips_dcache.vhd 1.19: + * CPUs/MIPS/src/core/mips_icache.vhd 1.14: + - added MRDY_O for I/D-Cache + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.fdo 1.12: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.18: + * CPUs/MIPS/src/bootloader.ROM.vhd 1.6: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-22 Jens + * CPUs/MIPS/sim/tb_mips_top_syn.fdo 1.1: + * CPUs/MIPS/sim/tb_mips_top_syn.wdo 1.3: + * CPUs/MIPS/src/mips_top_syn.vhd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-17 Jens + * misc/gpio_wb.vhd 1.8: + - added to_01() to timer counter, to avoid simulation warnings + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-14 Jens + * CPUs/MIPS/sim/tb_mips_top.wdo 1.17: + * CPUs/MIPS/src/core/mips_dcache.vhd 1.18: + * CPUs/MIPS/src/core/mips_icache.vhd 1.13: + - cleaned up + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-13 Jens + * FIFO/sim/tb_gray_counter.wdo 1.2: + * FIFO/src/gray_counter.vhd 1.3: + * FIFO/src/tb_gray_counter.vhd 1.2: + - cleaned up + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-12 Jens + * FIFO/src/tb_fifo_async.vhd 1.2: + * VGA_ctrl/src/vga_frontend64.vhd 1.24: + - added new FIFO generics + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-11 Jens + * FIFO/src/fifo_async.vhd 1.4: + * FIFO/src/fifo_async_ctrl.vhd 1.5: + * FIFO/src/fifo_sync.vhd 1.6: + * FIFO/src/fifo_sync_ctrl.vhd 1.5: + - added new FIFO generics + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.27: + - added new FIFO generics + - no STB_O if Bus input FIFO full. + => Bus out FIFO is read if SRDY_I = '1' and MRDY_O = '1' + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-09 Jens + * CPUs/MIPS/src/tb_mips_top.vhd 1.22: + * SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd 1.4: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl.vhd 1.4: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend64_wb.vhd 1.6: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.12: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.9: + * SDRAM/ddr_sdr_v1_5/src/sdram_types.vhd 1.4: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend64_wb.vhd 1.6: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.9: + * VGA_ctrl/src/clkgen_virtex4.vhd 1.4: + * misc/async_port_wb.vhd 1.15: + * misc/async_types.vhd 1.7: + * misc/clockgen_virtex4.vhd 1.3: + * misc/gpio_wb.vhd 1.6: + * misc/utils_pkg.vhd 1.4: + * ps2_port/src/ps2_core.vhd 1.3: + * ps2_port/src/ps2_wb.vhd 1.4: + - changed frequencies into MHz units (real data type) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/sdram_types.vhd 1.5: + * misc/async_types.vhd 1.8: + - to_cycles() now correctly rounded + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/gpio_wb.vhd 1.7: + * ps2_port/src/ps2_core.vhd 1.4: + - fixed rounding issue in usec prescaler + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd 1.5: + * misc/async_port_wb.vhd 1.16: + Minor changes to max cycle count + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/utils_pkg.vhd 1.5: + - improved UTILS_FREQ_M(), UTILS_FREQ_D(). + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-08 Jens + * misc/gpio_wb.vhd 1.5: + - added f_syscll_hz generic + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-07 Jens + * CPUs/MIPS/src/async_defs.vhd 1.8: + * SDRAM/ddr_sdr_v1_5/src/sdram_config.vhd 1.4: + * SDRAM/ddr_sdr_v1_5/src/sdram_types.vhd 1.3: + - made time specs in nano seconds + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.fdo 1.11: + - added asynchronous BUS FIFOs + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * FIFO/src/fifo_async.vhd 1.3: + * FIFO/src/fifo_async_ctrl.vhd 1.4: + - added read enable for DPRAM. Inhibits dout to be altered if FIFO is already empty on reads + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend64_wb.wdo 1.3: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/async_port_wb.vhd 1.14: + * misc/async_types.vhd 1.5: + - made time specs in nano seconds, thus independent of clock + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd 1.3: + * SDRAM/ddr_sdr_v1_5/src/sdram_config.vhd 1.3: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl.vhd 1.3: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend64_wb.vhd 1.5: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.11: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.8: + * SDRAM/ddr_sdr_v1_5/src/sdram_types.vhd 1.2: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend64_wb.vhd 1.5: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.8: + - made time specs in SDRAM_config independent of SDRAM clock + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/async_types.vhd 1.6: + - bugfix in to_cycles() + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.26: + * CPUs/MIPS/src/core/mips_top.vhd 1.17: + * CPUs/MIPS/src/tb_mips_top.vhd 1.21: + - added asynchronous BUS FIFOs + - added cpu_clk + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * FIFO/src/fifo_sync.vhd 1.5: + * FIFO/src/fifo_sync_ctrl.vhd 1.4: + - cleaned up + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-02-06 Jens + * CPUs/MIPS/src/core/mips_dcache.vhd 1.17: + Minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend64_wb.fdo 1.5: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo 1.7: + * SDRAM/ddr_sdr_v1_5/src/reset_virtex4.vhd 1.2: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.7: + - removed module reset_virtex4 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.wdo 1.16: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.wdo 1.5: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.25: + - added 16-depth Bus input FIFO (2 cycles additional latency) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-01-31 Jens + * CPUs/MIPS/tools/Makefile 1.5: + * CPUs/MIPS/tools/src/flashgen.c 1.3: + * CPUs/MIPS/tools/src/romgen.c 1.5: + Renamed old to new + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2010-01-09 Jens + * CPUs/MIPS/todo.txt 1.7: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-12-06 Jens + * ps2_port/src/ps2_wb.vhd 1.3: + - added states of pins clk and data to status register + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-29 Jens + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.10: + * VGA_ctrl/src/vga_frontend64.vhd 1.23: + - register set extended for future extensions + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.10: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-28 Jens + * VGA_ctrl/src/vga_frontend64.vhd 1.22: + - bugfix: BLIT IRQ-ack had no effect + - increased BLIT chunk-size to 512 QWORDs + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-27 Jens + * CPUs/MIPS/dist/tmpl/tb_mips_top.vhd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/mips_sys.vhd 1.3: + - added 'page_mode_en' inputs for async_port + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/mdist 1.10: + - overwrite src-DIR with tmpl/tb_mips_top.vhd + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/tb_mips_top.wdo 1.2: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-25 Jens + * VGA_ctrl/todo.txt 1.7: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-24 Jens + * CPUs/MIPS/src/core/mips_biu.vhd 1.24: + - bugfix: instructions uncached LW => cached LW (with cache-miss) was buggy. + Symptoms: + ... + 1.: lw $a0, 32($s0) # Uncached load from memory mapped I/O + 2.: lw $a2, 4($v0) # Cached load and cache-miss. + # $a0 receives same value as $a2. + # CPU skips writing $a0 due to busy flag of D-Cache, + # which is already active in the previous cycle + ... + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.20: + - Loads image for bugfix: instructions uncached LW => cached LW (with cache-miss) was buggy. + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.16: + * CPUs/MIPS/src/core/mips_icache.vhd 1.12: + - removed unused 'en' pin. + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/notes.txt 1.8: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.15: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-22 Jens + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.9: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_types.vhd 1.5: + - set 'f_pxl_clk' of 'ts_vga_testbench' tp 40MHz + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.17: + - added BLITTER + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.19: + - bugfix blitter reset + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.18: + - corrected blit NX which has to be divided by 2 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.8: + - added BLITTER tests + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.21: + - blitter FIFO is reseted on every new request + - blitter always avaliable regardless of MSTEN + - blit writes finish on blit_fifo_empty. Chunk counter only used for reads + - premature finish of blit reads if NX*NY satisfied. No more chunk granularity + - set BLIT_CHUNK_SIZE to 128 double-pixels + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.9: + - added blitter loop + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.20: + - added blitter completion interrupt + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-21 Jens + * VGA_ctrl/src/vga_frontend64.vhd 1.16: + - added Blitter registers + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-19 Jens + * VGA_ctrl/sim/tb_vga_frontend64.fdo 1.5: + - added sync FIFO for busout-FIFO + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.14: + - increased bous-FIFO depth to 2 bits, to avoid bus-stalls + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.15: + - buf_chg_ack also on 'host_fb_back' write + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.13: + - added busout-FIFO for future multi-sourced master capability (VGA-scan, blitter) + Bus-out FIFO improved timing so much and leads to 300 less Slice - FIFOs are great! + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-15 Jens + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.7: + - added RDY generator => SLAVE is not always ready => better test. + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/ddr_phy_virtex4.vhd 1.3: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend64_wb.vhd 1.4: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.10: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.6: + - removed 'sdr_data_req_r' + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/todo.txt 1.4: + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.8: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.12: + - removed (quick and dirty) copy of front-Pointer to back-Pointer on buffer change. back-Pointer keeps host written value. + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-11 Jens + * SDRAM/ddr_sdr_v1_5/todo.txt 1.2: + * SDRAM/ddr_sdr_v1_5/todo.txt 1.3: + * VGA_ctrl/todo.txt 1.6: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-09 Jens + * VGA_ctrl/src/vga_frontend64.vhd 1.10: + - renamed buffers to fb_front and fb_back + - fb_front is writable by host only if msten = '0'. fb_back is writable by host every time. + - fb_front and fb_back are changed after complete frame. Controller can issue buffer-change Interrupt + - packed resx, resy and fps into one 32-bit register + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.11: + - minor changes to make ISE meet timing + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.6: + - changes due to packing of resx, resy and fps into one 32-bit register + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.7: + * VGA_ctrl/todo.txt 1.5: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-08 Jens + * uart/uart_wb.vhd 1.9: + - minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.9: + - bugfix: added 'bufchg_irq_en' to registers + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.5: + * VGA_ctrl/src/vga_frontend64.vhd 1.8: + - added double buffer + - added INT_O on buffer change + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.5: + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.6: + * VGA_ctrl/todo.txt 1.3: + * VGA_ctrl/todo.txt 1.4: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-07 Jens + * ps2_port/src/ps2_core.vhd 1.2: + * ps2_port/src/tb_ps2_core.vhd 1.2: + - added error flags + - RX abort when rx_buffer already full (error flag set) + - added parity error flag + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * ps2_port/src/ps2_wb.vhd 1.2: + - added error flags + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/char_gen.vhd 1.5: + - turned all sys_clk-related async. resets to sys_clk synchronous resets + - scroll-disable when cursor y-pos was set + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * ps2_port/sim/tb_ps2_core.fdo 1.2: + * ps2_port/sim/tb_ps2_core.wdo 1.2: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-06 Jens + * ps2_port/sim/tb_ps2_core.fdo 1.1: + * ps2_port/sim/tb_ps2_core.wdo 1.1: + * ps2_port/src/debounce.vhd 1.1: + * ps2_port/src/ps2_core.vhd 1.1: + * ps2_port/src/ps2_phy_virtex.vhd 1.1: + * ps2_port/src/ps2_wb.vhd 1.1: + * ps2_port/src/tb_ps2_core.vhd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-05 Jens + * VGA_ctrl/sim/tb_vga_frontend.fdo 1.5: + * VGA_ctrl/sim/tb_vga_frontend64.fdo 1.4: + * VGA_ctrl/src/tb_vga_frontend.vhd 1.6: + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.4: + - removed clkgen. VGA-clock generated in TB + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/sim/tb_vga_frontend.wdo 1.4: + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.4: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-04 Jens + * SDRAM/ddr_sdr_v1_5/doc/SDRAM_CTRL.vsd 1.2: + - Minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend64_wb.fdo 1.4: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo 1.6: + - minor bugfix (inclusion of distributed DPRAM, which doesn't exist) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.wdo 1.4: + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.3: + * VGA_ctrl/todo.txt 1.2: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/char_gen.vhd 1.4: + - added cursor position status port + - 'dout' is set to last written character + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/todo.txt 1.1: + * VGA_ctrl/todo.txt 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend.vhd 1.6: + * VGA_ctrl/src/vga_frontend64.vhd 1.7: + - changed register rudimentary register layout (new offsets!) + - added new regsiter features: status/ctrl register cursor position, screen resolution + + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/clkgen_virtex4.vhd 1.3: + - added BUFG for clk_out + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/tb_vga_frontend.vhd 1.5: + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.3: + - more documentation + - more tests + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/async_port_wb.vhd 1.13: + - minor bugfix (width mismatch) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-03 Jens + * VGA_ctrl/src/vga_backend.vhd 1.4: + * VGA_ctrl/src/vga_frontend.vhd 1.5: + * VGA_ctrl/src/vga_frontend64.vhd 1.6: + - pulled out clkgen. vga_clk is now provided from higher level + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend64_wb.vhd 1.4: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.7: + - Minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend64_wb.wdo 1.2: + * VGA_ctrl/sim/tb_vga_frontend.wdo 1.3: + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.2: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/tb_vga_frontend.vhd 1.4: + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.2: + - added clkgen for vga + - initialized master-mode + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/sim/tb_vga_frontend.fdo 1.4: + * VGA_ctrl/sim/tb_vga_frontend64.fdo 1.3: + * VGA_ctrl/src/char_gen.vhd 1.3: + - include utils_pkg + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend64_wb.fdo 1.3: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo 1.5: + - include async. FIFO + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/utils_pkg.vhd 1.3: + - added helper functions for DCM frequency synthesis + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend64_wb.vhd 1.2: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.8: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.3: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend64_wb.vhd 1.2: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.5: + - SDRAM can now operate at different speed than BUS clock + - separated bus-clock (sys_clk) and SDRAM-clocks + - added async. FIFOs for clock domain separation + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_4/doc/SDRAM_CTRL.vsd 1.1: + * SDRAM/ddr_sdr_v1_5/doc/SDRAM_CTRL.vsd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend64_wb.vhd 1.3: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.6: + - added separate SD-CLK generator + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend64_wb.vhd 1.3: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.9: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.5: + - FIFO-depth of CMD-FIFO is not hardwired anymore. It's set to top-level FIFO-depth + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_types.vhd 1.4: + - put general helper functions to utils_pkg + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.4: + - changed CMD_FIFO_ADDR_WIDTH = 5 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/clkgen_virtex4.vhd 1.2: + * misc/clockgen_virtex4.vhd 1.2: + - cleaned up + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-11-02 Jens + * misc/async_port_wb.vhd 1.12: + - always specified leadout and release states, regardless of CPU-strobe (better timing) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend64.vhd 1.5: + - bugfix: set Pos X/Y : data was not set. + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-30 Jens + * misc/async_port_wb.vhd 1.11: + - some performance improvements + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.19: + - Minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.wdo 1.14: + * CPUs/MIPS/src/async_defs.vhd 1.6: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/async_port_wb.vhd 1.9: + - read-page cycle is minimum 2 cycles + - change assertion check: Read page pulse length must be greater than one + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/async_port_wb.vhd 1.10: + - writes have at least lead-in of one cycle if lead-in is speifified to 0 + - no data drive during lead-out + - no instant data drive in idle on 'en' + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/async_defs.vhd 1.7: + - zero lead-in / lead-out, + but added 4 cycles relelease necessary for writes. See tWR in datasheet) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-29 Jens + * misc/async_port_wb.vhd 1.8: + - Minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/async_defs.vhd 1.5: + - now 30 ns + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-28 Jens + * CPUs/JCpu/src/cpu_embedded.vhd 1.2: + * CPUs/JCpu/src/tb_cpu_embedded.vhd 1.2: + * CPUs/JCpu/src/tb_cpu_itest.vhd 1.2: + - removed XMEM-wait + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.wdo 1.13: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/JCpu/src/itest_irom.vhdl 1.2: + - removed ROM-depth generic + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.17: + - flash has access time of 25 ns + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/JCpu/sim/tb_cpu.fdo 1.2: + * CPUs/JCpu/sim/tb_cpu_embedded.fdo 1.2: + - changed ROM names to make TB run again + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.18: + - added 'page_mode_en' for async_port + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/async_defs.vhd 1.4: + * misc/async_types.vhd 1.4: + -added new page_read parameters + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/async_port_wb.vhd 1.7: + -added new page_read. Page read can be en/disabled + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-27 Jens + * CPUs/MIPS/doc/mips_sys_ml402.pdf 1.1: + Initial revison + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.16: + - added flash_we_n + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/async_port_timing.pdf 1.2: + * CPUs/MIPS/doc/mips_biu.pdf 1.2: + * CPUs/MIPS/doc/mips_drawings.vsd 1.15: + * CPUs/MIPS/doc/mips_jbus_timing.pdf 1.4: + * CPUs/MIPS/doc/mips_pipeline.pdf 1.3: + * CPUs/MIPS/doc/mips_pipeline_stages.pdf 1.3: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.12: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.14: + - async_port_timing: Changed names and timing diagram + to reflect V1.6 of async_port_wb.vhdl + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/async_port_wb.vhd 1.6: + - redesigned FSM. Zero leadin, zeroleadout and zero release is now possible + - added assertion check for zero r/w-pulses + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/async_defs.vhd 1.3: + * misc/async_types.vhd 1.3: + - changed names + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/bootloader.ROM.vhd 1.5: + - Booting from Flash is now from cached area (faster) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-24 Jens + * CPUs/MIPS/doc/mips_drawings.vsd 1.13: + - BIU: corrected drawing thickness of data lines + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * uart/uart_wb.vhd 1.8: + - removed force-TX-IRQ and TX-IRQ acknowledge + - TX-IRQ is always asserted if tx-FIFO is empty and tx-inten is active. + If TX-INT is not desired, it has to be switched off manually by TX-Inten. + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-18 Jens + * uart/uart_wb.vhd 1.7: + - added force TX-interrupt register bit (0x200) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-17 Jens + * CPUs/MIPS/doc/mips_sys.vsd 1.1: + Initial revison + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.22: + - changed NMI/RST behavior: reset exception entered after NMI/RST transition 1 => 0. + - BEV = 1 after NMI/RST (like hard reset) + - status not KUc,IEc not saved to KUp, IEp at NMI/RST (like hard reset) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/notes.txt 1.6: + * CPUs/MIPS/dist/tmpl/notes.txt 1.7: + * CPUs/MIPS/doc/J-MIPS.txt 1.4: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.11: + * CPUs/MIPS/src/bootloader.ROM.vhd 1.4: + * CPUs/MIPS/src/tb_mips_top.vhd 1.15: + * CPUs/MIPS/todo.txt 1.5: + * CPUs/MIPS/todo.txt 1.6: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/notes.txt 1.5: + update + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.25: + - Bugfix: register bypass with same target register, used for unaligned loads (LWL, LWR), was incorrect. + Newlib's memcpy() (MIPS-optimized) uses this for unaligned copy. + Consectutive load instructions without nops using same target register (which is legal) like + lw $1, 0(mem) + lwl $1, 1(mem) + or + lwl $1, 0(mem) + lwr $1, 1(mem) + or similar, lead to incorrect result. Now it's fixed. + + * CPUs/MIPS/doc/mips_drawings.vsd 1.12: + - added LWL/LWR bypass + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.23: + - added some comments + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-14 Jens + * CPUs/MIPS/src/core/mips_shifter.vhd 1.3: + Bugfix in gen_fill_mask_rom (wrong result on zero shift amounts due to width mismatch) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-13 Jens + * uart/uart_wb.vhd 1.6: + - fixed broken tx-interrupt + - added tx_int and rx_int to status reg + - tx-int is acked by writing to ctrl reg + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * uart/uart_tx.vhd 1.2: + - added tx-complete and tx-empty to ports + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-09 Jens + * uart/uart_wb.vhd 1.5: + - extended baudrate register from 8 to 16 bits, allowing very low baudrates + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-10-03 Jens + * CPUs/MIPS/sim/tb_mips_top.fdo 1.10: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.10: + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.24: + * CPUs/MIPS/src/core/mips_top.vhd 1.16: + * CPUs/MIPS/src/core/mips_types.vhd 1.16: + * CPUs/MIPS/src/tb_mips_top.vhd 1.14: + - added pin non-maskable interrupt (NMI). + Exception vector is reset vector at (X"BFC00000") + + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/notes.txt 1.4: + update + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/mdist 1.9: + update to R12 + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/mips_sys.vhd 1.2: + - added pin non-maskable interrupt (NMI). + Exception vector is reset vector at (X"BFC00000") + - added pin 'eb' for endian little/big choice. 'eb' is sampled at reset + - UART(): merged TX and RX interrupt to one interrupt line + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.21: + - added pin non-maskable interrupt (NMI). + Exception vector is reset vector at (X"BFC00000") + - Interrupt pending flags (IP) are not masked in hardware by IM. + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/files.dist 1.4: + - removed odd dist-versions of FIFOs and RAM + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-08-09 Jens + * CPUs/MIPS/todo.txt 1.4: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-08-08 Jens + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.23: + - minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.20: + - Status.TS tied high to indicate absence of an MMU + - Removed possibility of writng read-only status bits + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/notes.txt 1.3: + update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.13: + minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.9: + - added COP data lines to pipeline + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.11: + - detailed EX_stage according to implementation + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.10: + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.22: + - COP dout generated from MEM_ex_result and DMEM_din with multiplexer, to reduce fanout of MEM.data. + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-08-07 Jens + * misc/dpram_2w2r_virtex4.vhd 1.2: + del + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-05-10 Jens + * CPUs/MIPS/src/core/mips_top.vhd 1.15: + - doubled I-Cache size to 32kByte + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-05-09 Jens + * CPUs/MIPS/src/core/mips_shifter.vhd 1.2: + - replaced comparator-based fill-stage with rom-based fill-stage + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-05-08 Jens + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.21: + - minor changes (better timing) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.19: + - minor changes (bug) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.18: + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.20: + - Reset vector is now injected during reset like an ordinary exception. + This minimizes pc.nxt MUX (Better timing) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-05-06 Jens + * CPUs/MIPS/sim/tb_mips_top.fdo 1.9: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.9: + * CPUs/MIPS/src/core/mips_biu.vhd 1.23: + * CPUs/MIPS/syn/ise101/mips_top.prj 1.4: + * CPUs/MIPS/syn/ise101/mips_top_vhdl.prj 1.4: + - removed reference to fifo_sync_dist. + Use fifo_sync instead and specified ditributed ram_style + in XCF-file during synthesis + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.12: + - removed register output latch (latch introduced global clock buffer, which is deprecated) + - CPU is configured as BIG-endian + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-05-05 Jens + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.19: + * CPUs/MIPS/src/core/mips_types.vhd 1.15: + - renamed pc.is_branch:boolean to pc.branch_take:std_logic + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.17: + - removed register output latch (latch introduced global clock buffer, which is deprecated) + - added separate reg_pointer for read/write + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-05-03 Jens + * uart/uart_wb.vhd 1.4: + - removed INT_O_TX from UART. Use now common INT_O for RX/TX + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-05-01 Jens + * VGA_ctrl/src/vga_frontend64.vhd 1.4: + - added test color register base + 0x80 + - control signals derived from register file are noe registered for better timing + - mem_offset updated from vga_mem_offset wehn new frame begins + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-04-27 Jens + * CPUs/MIPS/src/core/mips_cop.vhd 1.16: + - SR(7 .. 0) are not writable in user-mode + - registered 'ctrl_out.int' for better timing + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-04-19 Jens + * CPUs/MIPS/src/core/mips_cop.vhd 1.15: + - status register is always writable + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * uart/uart_wb.vhd 1.3: + - added interrupt enable + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-04-17 Jens + * CPUs/MIPS/doc/memory_map.vsd 1.2: + * CPUs/MIPS/src/core/mips_cop.vhd 1.14: + - changed Exception vector from 0x80000180 to 0x80000080 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/async_port_timing.pdf 1.1: + * CPUs/MIPS/doc/memory_map.pdf 1.1: + * CPUs/MIPS/doc/memory_map.vsd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/gpio_wb.vhd 1.4: + - added 2. Interrupt timer + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-04-15 Jens + * CPUs/MIPS/tools/src/romgen.c 1.4: + - added switch EB/EL to switch endianess + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.13: + * CPUs/MIPS/src/core/mips_top.vhd 1.14: + * CPUs/MIPS/src/tb_mips_top.vhd 1.11: + - added port 'eb' for Endian-big selection + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.18: + - bugfix: wrong 'pa_offset' when big-endian and half-word load/store + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * uart/uart_wb.vhd 1.2: + - removed SEL for register writes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_types.vhd 1.14: + - minor improvements for load/store shifter + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-04-11 Jens + * CPUs/MIPS/src/core/mips_cop.vhd 1.12: + Reworked exception FSM: + - Pipeline is now flushed and finished and all dependencies are solved before entering exception handler + - User mode writes on status register are now correctly finished before status is altered by exception + - Processor stalls for 2 cycles after RFE to ensure that status register is correct in user mode + - Added int-port + + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_types.vhd 1.13: + - some new control signals in cop0_ctrl + - added exc-Flag in WB_stage + - simplified int signals + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_top.vhd 1.13: + - Int-port is now at cop instead of pipeline + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.17: + - reworked exception stuff + - removed int-port (it's now in cop) + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-04-07 Jens + * CPUs/MIPS/doc/mips_drawings.vsd 1.8: + - Update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-04-06 Jens + * CPUs/MIPS/doc/mips_drawings.vsd 1.7: + * CPUs/MIPS/doc/mips_pipeline_stages.pdf 1.2: + -Mips-Pipeline stages: added missing register for PC-Branch + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.6: + -Mips-Pipeline: added missing register for PC-Branch + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-30 Jens + * CPUs/MIPS/src/core/mips_dcache.vhd 1.15: + * CPUs/MIPS/src/core/mips_icache.vhd 1.11: + - redesigned + - added invalidate_all and invalidate_at control + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.11: + - removed weird feature, which prevents cop registers to be written in front of exception. + cop register behavior is now hopefully the same as general registers. + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_top.vhd 1.12: + - changed reset generator and added BIU-Reset signal + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.22: + - 'dcache_en' now doesn't depend on CYC_O_dmem_rd or write_busy + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-29 Jens + * CPUs/MIPS/src/core/mips_dcache.vhd 1.14: + * CPUs/MIPS/src/core/mips_icache.vhd 1.10: + - added control port + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-28 Jens + * CPUs/MIPS/src/core/mips_types.vhd 1.12: + - added cache_ctrl record. Used in c0_ctrl_out + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.10: + - added Cop instructions COP0 32, COP0 33, COP 34, COP0 35: + ICACHE_invalidate_at, ICACHE_invalidate_all, + DCACHE_invalidate_at, DCACHE_invalidate_all. + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.21: + - added cache_ctrl input + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_top.vhd 1.11: + - assigned c0_ctrl to BIU for cache_ctrl + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.16: + - removed MUX for RESET_VECTOR in proc_stage_pc: + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-27 Jens + * CPUs/MIPS/src/tb_mips_top.vhd 1.10: + * misc/gpio_wb.vhd 1.3: + - added timer inrterrupt + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-20 Jens + * CPUs/MIPS/src/core/mips_cop.vhd 1.9: + - cop ouput register is now latch (better timing) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/files.dist 1.3: + - removed idecode_rom.vhd + + + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.wdo 1.8: + - Update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-18 Jens + * CPUs/MIPS/src/core/mips_cop.vhd 1.8: + - added instructions 'lwc0' and 'swc0' for testing (which are usually invalid) + - due to cop_reg_we in MEM_Stage, the output register is removed + (timing is slightly degraded). The reg pointer is delayed instead by one cycle + - test-reg is now writable in user mode regardles of cop0 usability. + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_instr.vhd 1.5: + - added instructions 'lwcz' and 'swcz'. + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/todo.txt 1.3: + - Update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-17 Jens + * CPUs/MIPS/src/core/mips_types.vhd 1.11: + - new signal 'cop_read' in ctrl_lines + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_instr.vhd 1.4: + - more decoding of cop_signals. + New cop_read is now implemented into instruction decoder + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.fdo 1.8: + - removed idecode_rom.vhd + + + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_top.vhd 1.10: + - - removed cop_reg_rd + if cop is read is now implemented into instruction decoder + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.15: + - removed cop_reg_rd + if cop is read is now implemented into instruction decoder + - generate 'stall_all' signal if ID/EX/MEM stall is active + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.7: + - removed 'reg_rd' which is fed into pipeline. + if cop is read is now implemented into instruction decoder + - simplified use of stall signals + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-16 Jens + * CPUs/MIPS/src/core/mips_instr.vhd 1.3: + * CPUs/MIPS/src/core/mips_types.vhd 1.10: + - added COPz debugging identifier + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.14: + - 'cop_dout' is now generated in pipeline in MEM_STAGE. + This gives possibility to load cop with memory contents (LWCz). + - dmem_dout can be EX_STAGE.reg_b by default or cop_din if cop_instr_en is asserted. + This give possibility to store cop content to memory (SWCz) + - removed idecode_rom. Uses opcode_ctrl_lines() directly. + + + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.6: + - cop uses 'din' directly without delay. 'Din' is now generated in pipeline in MEM_STAGE. + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_instr.vhd 1.2: + - simplified instruction decoder and removed genrom functions + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_idecode_rom.vhd 1.2: + - deleted + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_types.vhd 1.9: + - added opcode debugging identfier MFCz, MTCz, CFCz, CTCz, BCTz, BCFz for COP functions + - removed COPz debugging identifier + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-15 Jens + * CPUs/MIPS/src/core/mips_types.vhd 1.7: + - common functions lg2() and po2() added + - reworked cop0_ctrl_in/out types + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_top.vhd 1.9: + - added cop0 here + - added cache line sizes to generic + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.5: + - Update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.13: + - removed cop0 + - added interface for external cop0 and copz + - reworked cop_read and cop_write signals. + Using only cop_read which is delay in pipeline + + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.13: + * CPUs/MIPS/src/core/mips_icache.vhd 1.9: + - cleaned up: removed lg2() and po2() to mips_types + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.4: + * CPUs/MIPS/doc/mips_jbus_timing.pdf 1.3: + - added detail to jbus-timing + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.20: + - added cache line sizes to generic + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_types.vhd 1.8: + - new release 12 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_cop.vhd 1.5: + - added cache config to generic to create cache info in upper 16 bits PrID + - unified control signals for later use with Copz + - cleaned up + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-10 Jens + * misc/gpio_wb.vhd 1.2: + - removed timer reset dring RST_I + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-08 Jens + * CPUs/MIPS/src/core/mips_biu.vhd 1.19: + - Uncached DMEM is now spec. conform from A0000000..BFFFFFFF (instead A0000000..AFFFFFFF) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-03-01 Jens + * CPUs/MIPS/dist/mdist 1.8: + * CPUs/MIPS/src/core/mips_types.vhd 1.6: + - new release 11 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/notes.txt 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/notes.txt 1.2: + - Update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-28 Jens + * CPUs/JCpu/src/core/chipreg.vhd 1.3: + * CPUs/JCpu/src/core/int_ctrl.vhd 1.2: + - removed edge trigger capabilty + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/JCpu/src/core/cpu.vhd 1.3: + - removed xmem_wait + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/JCpu/src/core/cpu_pkg.vhd 1.3: + - removed edge trigger capabilty + - removed xmem_wait + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/JCpu/src/core/chipreg.vhd 1.4: + * CPUs/JCpu/src/core/cpu_pkg.vhd 1.4: + * CPUs/JCpu/src/core/int_ctrl.vhd 1.3: + - removed interrupt polarity capabilty + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-16 Jens + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.12: + - bug-fix: pc_is_branch is now initialized at reset (fixes CPU unrecoverable state after reset) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/mdist 1.6: + - new release candidate 11 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.9: + - inreased flash and sram to 32kB + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/tmpl/mips_sys.vhd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/mdist 1.7: + - copies now mips_sys from templates + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-15 Jens + * CPUs/MIPS/sim/tb_mips_top.wdo 1.6: + - minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.wdo 1.7: + - Update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.3: + - added async_port timing + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_icache.vhd 1.7: + - reintroduced explicit 'rag_ram_re' + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.11: + * CPUs/MIPS/src/core/mips_types.vhd 1.5: + - put dependency signals 'imem_dep', 'dmem_dep' and 'mul_dep' into structure for easier debugging + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.12: + * CPUs/MIPS/src/core/mips_icache.vhd 1.8: + - Cleaned up + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-14 Jens + * CPUs/MIPS/tools/Makefile 1.4: + - added install target + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/mdist 1.5: + - new revision 10b + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-13 Jens + * VGA_ctrl/src/vga_frontend.vhd 1.4: + * VGA_ctrl/src/vga_frontend64.vhd 1.3: + - vga_frontend* used wrong raster coords (y was swapped) - fixed + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-11 Jens + * CPUs/MIPS/src/core/mips_dcache.vhd 1.10: + * CPUs/MIPS/src/core/mips_icache.vhd 1.5: + - removed explicit tag_ram_read + - remove state 'rd_cache' + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.wdo 1.5: + - minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.10: + * CPUs/MIPS/src/core/mips_top.vhd 1.8: + - put reset-logic outside pipeline + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.11: + * CPUs/MIPS/src/core/mips_icache.vhd 1.6: + - re-added state 'rd_cache' + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-09 Jens + * CPUs/MIPS/tools/src/romgen.c 1.3: + - TCL-gen for Chipscope 10.1 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/mdist 1.4: + - new revision 10a + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-08 Jens + * CPUs/MIPS/src/core/mips_reg.vhd 1.2: + - removed RAM-init during synthesizing + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.9: + - R0 clear during reset + - dmem_be active also during read + + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.wdo 1.4: + * CPUs/MIPS/src/tb_mips_top.vhd 1.8: + - use async_be + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/async_defs.vhd 1.2: + * misc/async_port_wb.vhd 1.5: + * misc/async_types.vhd 1.2: + - added async_be + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.18: + - SEL_O asserts correctly for uncached reads + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-07 Jens + * CPUs/MIPS/src/bootloader.ROM.vhd 1.3: + - new build + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/mdist 1.3: + - copies doc/*.txt to release + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/tb_mips_top.vhd 1.7: + -added generic map for 'mips_top' + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-06 Jens + * CPUs/MIPS/dist/mdist 1.2: + * CPUs/MIPS/doc/J-MIPS.txt 1.3: + * CPUs/MIPS/src/core/mips_types.vhd 1.4: + - new revision 10 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-02-04 Jens + * CPUs/MIPS/src/core/mips_dcache.vhd 1.9: + - removed stall during instant_raw on same word_index (improves performance) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-31 Jens + * CPUs/MIPS/doc/J-MIPS.txt 1.2: + - added performance values for different cache sizes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/dist/files.dist 1.2: + - renamed fifo + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-30 Jens + * CPUs/MIPS/syn/ise101/mips_top.prj 1.3: + * CPUs/MIPS/syn/ise101/mips_top_vhdl.prj 1.3: + - update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.fdo 1.7: + * CPUs/MIPS/todo.txt 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl.fdo 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_fifo.fdo 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_fifo.wdo 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_lin_r_rand_w.fdo 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_lin_w_rand_r.fdo 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_rand_addr.fdo 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_rand_rw.fdo 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdram_ctrl_frontend.fdo 1.2: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdram_ctrl_frontend.wdo 1.2: + * SDRAM/ddr_sdr_v1_4/src/fifo_sync.vhd 1.2: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend64_wb.fdo 1.2: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo 1.4: + * VGA_ctrl/sim/tb_vga_frontend.fdo 1.3: + * VGA_ctrl/sim/tb_vga_frontend64.fdo 1.2: + * ac97_ctrl/sim/tb_ac97_wb.fdo 1.2: + * ac97_ctrl/src/core/ac97_wb.vhd 1.2: + * filter/src/tb_fir_semi_parallel.vhd 1.11: + * radio/ddc/sim/tb_ddc.fdo 1.6: + * radio/ddc/src/syn_ddc.vhd 1.8: + - renamed fifo_*sync_ctrl + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * FIFO/sim/tb_async_fifo_ctrl.fdo 1.2: + * FIFO/sim/tb_async_fifo_ctrl.wdo 1.2: + * FIFO/sim/tb_sync_fifo_ctrl.fdo 1.2: + * FIFO/sim/tb_sync_fifo_ctrl.wdo 1.2: + * FIFO/src/dpram.vhd 1.2: + * FIFO/src/tb_async_fifo_ctrl.vhd 1.2: + * FIFO/src/tb_sync_fifo_ctrl.vhd 1.2: + - deleted + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * FIFO/src/fifo_async.vhd 1.2: + * FIFO/src/fifo_ctrl_pkg.vhd 1.2: + * FIFO/src/fifo_sync.vhd 1.4: + * FIFO/src/gray_counter.vhd 1.2: + - added header + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * FIFO/src/dpram_1w1r.vhd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * VGA_ctrl/src/vga_frontend.vhd 1.3: + * VGA_ctrl/src/vga_frontend64.vhd 1.2: + - renamed fifo ports + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * FIFO/src/fifo_async_ctrl.vhd 1.3: + * FIFO/src/fifo_sync_ctrl.vhd 1.3: + * FIFO/src/fifo_sync_dist.vhd 1.2: + * FIFO/src/tb_fifo_async.vhd 1.1: + * FIFO/src/tb_fifo_sync.vhd 1.1: + - renamed + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-24 Jens + * CPUs/MIPS/src/bootloader.ROM.vhd 1.2: + using gcc 4.3.2 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_top.vhd 1.7: + - generic for cache sizes + - JBus-ports are unsigned instead of word_t + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.17: + * CPUs/MIPS/src/tb_mips_top.vhd 1.6: + - JBus-ports are unsigned instead of word_t + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/tools/Makefile 1.3: + * CPUs/MIPS/tools/src/flashgen.c 1.2: + - flashgen: new bigendian target + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-23 Jens + * CPUs/MIPS/doc/J-MIPS.txt 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_drawings.vsd 1.2: + * CPUs/MIPS/doc/mips_jbus_timing.pdf 1.2: + - JBus-timing: removed ACK_I during write. + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-21 Jens + * CPUs/MIPS/dist/files.dist 1.1: + * CPUs/MIPS/dist/mdist 1.1: + * CPUs/MIPS/dist/tmpl/gpl-3.0.txt 1.1: + * CPUs/MIPS/dist/tmpl/hello.flash.bin 1.1: + * CPUs/MIPS/dist/tmpl/tb_mips_top.wdo 1.1: + * CPUs/MIPS/doc/mips_biu.pdf 1.1: + * CPUs/MIPS/doc/mips_drawings.vsd 1.1: + * CPUs/MIPS/doc/mips_jbus_timing.pdf 1.1: + * CPUs/MIPS/doc/mips_pipeline.pdf 1.1: + * CPUs/MIPS/doc/mips_pipeline_stages.pdf 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/doc/mips_pipeline.pdf 1.2: + - update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-20 Jens + * CPUs/MIPS/src/core/mips_types.vhd 1.3: + - changed to rev.9 + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.8: + - removed commented lines + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-19 Jens + * CPUs/MIPS/sim/tb_mips_top.fdo 1.6: + * CPUs/MIPS/src/tb_mips_top.vhd 1.5: + - removed PCK_FIO (not needed) + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-18 Jens + * CPUs/MIPS/sim/tb_mips_top.fdo 1.5: + * CPUs/MIPS/src/tb_mips_top.vhd 1.4: + * CPUs/MIPS/tools/src/ramgen.c 1.2: + * CPUs/MIPS/tools/src/romgen.c 1.2: + - Minor changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/JCpu/src/core/chipreg.vhd 1.2: + * CPUs/JCpu/src/core/cpu.vhd 1.2: + * CPUs/JCpu/src/core/cpu_pkg.vhd 1.2: + - rename 'page' to 'bank' + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * misc/async_port_wb.vhd 1.4: + - added SEL_I and multiple write-enables on async port + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/tools/Makefile 1.2: + - added flashgen build + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/async_defs.vhd 1.1: + * CPUs/MIPS/src/bootloader.ROM.vhd 1.1: + * CPUs/MIPS/tools/src/flashgen.c 1.1: + * misc/async_types.vhd 1.1: + Initial version + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top_syn.tdo 1.2: + * CPUs/MIPS/sim/tb_mips_top_syn.wdo 1.2: + * CPUs/MIPS/src/fibonacci.ROM_ld.vhd 1.2: + * CPUs/MIPS/src/irom_hello.vhd 1.2: + * CPUs/MIPS/src/irom_test1.vhd 1.2: + * CPUs/MIPS/src/irom_test2.vhd 1.2: + * CPUs/MIPS/src/irom_test3.vhd 1.2: + * CPUs/MIPS/src/irom_test4.vhd 1.2: + * CPUs/MIPS/src/irom_test5.vhd 1.2: + * CPUs/MIPS/src/irom_test6.vhd 1.2: + * CPUs/MIPS/src/irom_test_addsub.vhd 1.2: + * CPUs/MIPS/src/irom_test_slt.vhd 1.2: + * CPUs/MIPS/src/irom_test_slti.vhd 1.2: + * CPUs/MIPS/src/irom_test_sub.vhd 1.2: + * CPUs/MIPS/src/mips_embedded.vhd 1.2: + * CPUs/MIPS/src/mips_embedded_syn.vhd 1.2: + * CPUs/MIPS/src/ram.vhd 1.2: + * CPUs/MIPS/src/ram_ld.vhd 1.2: + * CPUs/MIPS/src/ram_sim.vhd 1.2: + * CPUs/MIPS/src/rmd160_test.ROM_ld.vhd 1.2: + * CPUs/MIPS/src/tb_mips_embedded.vhd 1.2: + * CPUs/MIPS/src/tb_mips_embedded_syn.vhd 1.2: + * CPUs/MIPS/src/testbench.ROM_ld.vhd 1.2: + * CPUs/MIPS/tools/insrom.rb 1.2: + * CPUs/MIPS/tools/irom.vhd.tpl 1.2: + * CPUs/MIPS/tools/irom_ld.vhd.tpl 1.2: + * CPUs/MIPS/tools/make.sh 1.2: + * CPUs/MIPS/tools/rom.tcl.tpl 1.2: + - deleted + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.fdo 1.4: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.3: + * CPUs/MIPS/src/tb_mips_top.vhd 1.3: + - major changes + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + +2009-01-16 Jens + * CPUs/MIPS/syn/ise101/mips_top.prj 1.2: + * CPUs/MIPS/syn/ise101/mips_top_vhdl.prj 1.2: + - update + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_top.vhd 1.6: + - renamed bui to biu + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/src/core/mips_biu.vhd 1.16: + - renamed + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_top.fdo 1.3: + - renamed bui, icache and dcache + Committed on the Free edition of March Hare Software CVSNT Server. + Upgrade to CVS Suite for more features and support: + http://march-hare.com/cvsnt/ + + * CPUs/MIPS/sim/tb_mips_embedded.fdo 1.2: + * CPUs/MIPS/sim/tb_mips_embedded.wdo 1.2: + * CPUs/MIPS/sim/tb_mips_embedded_syn.fdo 1.2: + * CPUs/MIPS/sim/tb_mips_embedded_syn.tdo 1.2: + * CPUs/MIPS/sim/tb_mips_embedded_syn.wdo 1.2: + * CPUs/MIPS/sim/tb_mips_muldiv.ndo 1.2: + * CPUs/MIPS/sim/tb_mips_muldiv.sdo 1.2: + * CPUs/MIPS/sim/tb_mips_top.mdo 1.2: + * CPUs/MIPS/sim/tb_mips_top.mwdo 1.2: + * CPUs/MIPS/sim/tb_mips_top.sdo 1.2: + * CPUs/MIPS/sim/tb_mips_top_syn.mdo 1.2: + - deleted + +2009-01-15 Jens + * CPUs/MIPS/sim/tb_mips_top.fdo 1.2: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.2: + * CPUs/MIPS/src/tb_mips_top.vhd 1.2: + - changed to J-Bus interface + +2009-01-14 Jens + * radio/mix/sim/tb_mix_cpx.fdo 1.2: + * radio/mix/sim/tb_mix_real.fdo 1.2: + * radio/mix/sim/tb_undc_real.fdo 1.2: + * radio/mix/src/mix_cpx.vhd 1.2: + * radio/mix/src/mix_real.vhd 1.2: + * radio/mix/src/tb_mix_cpx.vhd 1.2: + * radio/mix/src/tb_mix_real.vhd 1.2: + * radio/mix/src/tb_undc_real.vhd 1.2: + * radio/mix/src/undc_real.vhd 1.2: + - uses common fixed_pkg + + * misc/dpram_2w2r.vhd 1.2: + - changed read, write order (should have no effect) + + * radio/mix/sim/tb_undc_real.fdo 1.3: + - removed reference to mix_pkg + + * radio/mix/src/mix_pkg.vhd 1.2: + - deleted + +2009-01-13 Jens + * radio/ddc/sim/tb_results.m 1.5: + - removed decimation in m-script (which is done in CFIR) + + * filter/src/fir_stage_sys.vhd 1.12: + - bugfix 'x_out' register + + * filter/sim/tb_fir_semi_parallel.wdo 1.7: + * filter/src/fir_semi_parallel.vhd 1.15: + * filter/src/fir_stage_sys.vhd 1.11: + * filter/src/tb_fir_semi_parallel.vhd 1.10: + * radio/ddc/src/ddc.vhd 1.13: + - fir_stage_sys only uses pipe_latency as parameter + +2009-01-12 Jens + * radio/ddc/src/ddc.vhd 1.12: + - removed adding of one bit to cic_stages + + * misc/mult_signed.vhd 1.1: + Initial version + +2009-01-11 Jens + * filter/sim/tb_fir_semi_parallel.wdo 1.6: + * filter/src/fir_stage_sys.vhd 1.10: + * filter/src/fir_stage_sys.vhd 1.9: + * filter/src/tb_fir_semi_parallel.vhd 1.9: + * radio/ddc/src/ddc.vhd 1.10: + * radio/ddc/src/ddc.vhd 1.11: + * radio/ddc/src/syn_ddc.vhd 1.7: + - Minor changes + + * fixed/fixed_pkg_c.vhd 1.2: + deleted + + * filter/src/delay_line.vhd 1.6: + - removed 'ce' + + * radio/ddc/src/ddc.vhd 1.9: + * radio/ddc/src/tb_ddc.vhd 1.7: + - Uses decimating CFIR (decimate by 2) + + * filter/src/fir_semi_parallel.vhd 1.13: + * filter/src/tb_fir_semi_parallel.vhd 1.8: + - decimating is now working + + * filter/src/fir_semi_parallel.vhd 1.14: + - Coeff RAMs have no 'ce' for read + + * fixed/fixed_util_pkg.vhd 1.1: + Initial version + +2009-01-10 Jens + * filter/src/fir_semi_parallel.vhd 1.11: + * filter/src/tb_fir_semi_parallel.vhd 1.7: + - new signal 'start' to trigger FIR process + use din_vld for data load. This permits decimation FIR filtering + + * filter/sim/tb_fir_semi_parallel.fdo 1.6: + * filter/sim/tb_fir_semi_parallel.wdo 1.5: + * radio/ddc/sim/tb_results.m 1.3: + * radio/ddc/sim/tb_results.m 1.4: + * radio/ddc/src/tb_ddc.vhd 1.6: + - Minor changes + + * radio/ddc/sim/tb_ddc.fdo 1.5: + * radio/ddc/sim/tb_ddc.wdo 1.6: + * radio/ddc/src/ddc.vhd 1.8: + - Prepared with FIFO for decimating FIR + + * filter/src/fir_semi_parallel.vhd 1.12: + - reverted to 1.10 + - kept signal 'start' to trigger FIR process + + * filter/src/filter_pkg.vhd 1.4: + - Lowpass prototype: omega is fraction of fs/2 + +2009-01-09 Jens + * radio/ddc/src/ddc.vhd 1.7: + * radio/ddc/src/syn_ddc.vhd 1.6: + * radio/ddc/src/tb_ddc.vhd 1.5: + - added unfiltered output at ddc for eval + + * radio/ddc/sim/tb_ddc.wdo 1.5: + * radio/ddc/sim/tb_results.m 1.2: + - Cleaned up + +2009-01-08 Jens + * filter/src/fir_semi_parallel.vhd 1.10: + - coef input registered + +2009-01-06 Jens + * radio/ddc/sim/tb_ddc.fdo 1.4: + * radio/ddc/sim/tb_ddc.wdo 1.4: + * radio/ddc/src/ddc.vhd 1.6: + - changed iterative CFIR wirh semi-parallel version + + * radio/ddc/src/syn_ddc.vhd 1.5: + - Cleaned up + + * filter/src/fir_stage_sys.vhd 1.8: + - added assertion check for min coef_latency + +2009-01-05 Jens + * filter/sim/tb_fir_semi_parallel.fdo 1.5: + * filter/sim/tb_fir_semi_parallel.wdo 1.4: + - Minor changes + + * filter/src/fir_semi_parallel.vhd 1.8: + - added dedicated DPRAM for COEFFS + + * filter/src/delay_line.vhd 1.5: + - Cleaned up + + * filter/src/fir_stage_sys.vhd 1.7: + - fixed missing CE at yout + + * filter/src/delay_line.vhd 1.4: + - added RAM-based architecture + + * filter/src/fir_semi_parallel.vhd 1.9: + - use RAM-based delayline + +2009-01-04 Jens + * filter/src/delay_line.vhd 1.2: + - added shift_en input + + * filter/sim/tb_fir_semi_parallel.fdo 1.3: + * filter/sim/tb_fir_semi_parallel.fdo 1.4: + * filter/src/delay_line.vhd 1.3: + * filter/src/tb_fir_semi_parallel.vhd 1.6: + - Minor changes + + * filter/src/fir_semi_parallel.vhd 1.7: + * filter/src/fir_stage_sys.vhd 1.6: + * filter/src/tb_fir_stage_sys.vhd 1.4: + - removed reset from fir_stage_sys + + * filter/src/fir_semi_parallel.vhd 1.6: + * filter/src/tb_fir_semi_parallel.vhd 1.5: + - fixed rdy-signal + + * filter/sim/tb_fir_semi_parallel.fdo 1.2: + * filter/sim/tb_fir_semi_parallel.wdo 1.3: + * filter/src/fir_semi_parallel.vhd 1.5: + * filter/src/tb_fir_semi_parallel.vhd 1.4: + - input data rate can be lower than filter + + * filter/src/fir_semi_parallel.vhd 1.3: + - minor mods to accu_ld_pipe + + * filter/src/fir_semi_parallel.vhd 1.4: + * filter/src/fir_stage_sys.vhd 1.5: + * filter/src/tb_fir_semi_parallel.vhd 1.3: + - added ce + +2009-01-03 Jens + * filter/src/fir_stage_sys.vhd 1.3: + - bug fix coef-pipe + + * filter/sim/tb_fir_semi_parallel.fdo 1.1: + * filter/sim/tb_fir_semi_parallel.wdo 1.1: + * filter/src/delay_line.vhd 1.1: + * filter/src/fir_pkg.vhd 1.1: + * filter/src/fir_semi_parallel.vhd 1.1: + * filter/src/tb_fir_semi_parallel.vhd 1.1: + - Intital revision + + * filter/sim/tb_fir_iterative.fdo 1.3: + * filter/sim/tb_fir_iterative.wdo 1.2: + * filter/sim/tb_fir_parallel.fdo 1.3: + * filter/sim/tb_fir_stage.fdo 1.3: + * filter/sim/tb_fir_stage_sys.fdo 1.2: + * filter/src/fir_iterative.vhd 1.5: + * filter/src/fir_parallel.vhd 1.5: + * filter/src/fir_stage.vhd 1.4: + * filter/src/fir_stage_sys.vhd 1.4: + * filter/src/tb_fir_iterative.vhd 1.4: + * filter/src/tb_fir_parallel.vhd 1.7: + * filter/src/tb_fir_stage.vhd 1.5: + * filter/src/tb_fir_stage_sys.vhd 1.3: + - uses only fir_pkg and filter_pkg for FIR + + * filter/sim/tb_fir_semi_parallel.wdo 1.2: + * filter/src/fir_semi_parallel.vhd 1.2: + * filter/src/tb_fir_semi_parallel.vhd 1.2: + - minor mods to vld_pipe + +2009-01-02 Jens + * filter/src/fir_parallel_pkg.vhd 1.5: + - moved fixed_array_t to fixed_util_pkg + + * filter/src/filter_pkg.vhd 1.3: + * radio/cordic/src/cordic_pkg.vhd 1.5: + - moved real_array_t to fixed_util_pkg + + * radio/ddc/sim/tb_ddc.fdo 1.3: + * radio/ddc/sim/tb_ddc.wdo 1.3: + * radio/ddc/src/ddc.vhd 1.4: + * radio/ddc/src/tb_ddc.vhd 1.4: + - added CFIR + + * radio/ddc/src/syn_ddc.vhd 1.4: + - Minor changes + + * filter/src/tb_fir_stage_sys.vhd 1.2: + - added coef_latency + + * filter/src/fir_stage_sys.vhd 1.2: + - added coef_latency + - y_dout registered + + * filter/src/fir_iterative_pkg.vhd 1.3: + - fix ntaps_bits + + * filter/src/fir_iterative.vhd 1.4: + - using fir_stage_sys instead of fir_stage + + * radio/ddc/src/ddc.vhd 1.5: + - simplification for coef-array + + * misc/utils_pkg.vhd 1.2: + - added real veriants of NextPower... + +2008-12-31 Jens + * filter/src/fir_iterative.vhd 1.3: + * filter/src/fir_parallel.vhd 1.4: + * filter/src/fir_parallel_pkg.vhd 1.4: + * filter/src/fir_stage.vhd 1.3: + * filter/src/tb_fir_iterative.vhd 1.3: + * filter/src/tb_fir_parallel.vhd 1.6: + * filter/src/tb_fir_stage.vhd 1.4: + - removed sproto-calls due to crashes in synth tools + + * filter/sim/tb_fir_stage_sys.fdo 1.1: + * filter/sim/tb_fir_stage_sys.wdo 1.1: + * filter/src/fir_stage_sys.vhd 1.1: + * filter/src/tb_fir_stage_sys.vhd 1.1: + - Intital revision + +2008-12-30 Jens + * radio/decimator/CIC/src/cic_decim_pipe.vhd 1.3: + - added register after scaler + + * radio/decimator/CIC/sim/tb_cic_decim_pipe.wdo 1.2: + - Minor changes + + * filter/sim/tb_fir_iterative.fdo 1.2: + * filter/sim/tb_fir_parallel.fdo 1.2: + * filter/sim/tb_fir_stage.fdo 1.2: + * filter/src/filter_pkg.vhd 1.2: + * filter/src/fir_iterative.vhd 1.2: + * filter/src/fir_iterative_pkg.vhd 1.2: + * filter/src/fir_parallel.vhd 1.3: + * filter/src/fir_parallel_pkg.vhd 1.3: + * filter/src/fir_stage.vhd 1.2: + * filter/src/fir_stage_pkg.vhd 1.2: + * filter/src/tb_fir_iterative.vhd 1.2: + * filter/src/tb_fir_parallel.vhd 1.5: + * filter/src/tb_fir_stage.vhd 1.3: + * radio/cordic/sim/tb_cordic_pipe_top.fdo 1.2: + * radio/cordic/sim/tb_cordic_top.fdo 1.2: + * radio/cordic/src/cordic_pipe_post.vhd 1.3: + * radio/cordic/src/cordic_pipe_pre.vhd 1.3: + * radio/cordic/src/cordic_pipe_stage.vhd 1.3: + * radio/cordic/src/cordic_pipe_top.vhd 1.5: + * radio/cordic/src/cordic_pkg.vhd 1.4: + * radio/cordic/src/cordic_rom.vhd 1.2: + * radio/cordic/src/cordic_stage.vhd 1.2: + * radio/cordic/src/cordic_stage_post.vhd 1.2: + * radio/cordic/src/cordic_stage_pre.vhd 1.2: + * radio/cordic/src/cordic_top.vhd 1.2: + * radio/cordic/src/tb_cordic_pipe_top.vhd 1.2: + * radio/cordic/src/tb_cordic_top.vhd 1.2: + * radio/ddc/sim/tb_ddc.fdo 1.2: + * radio/ddc/sim/tb_ddc.wdo 1.2: + * radio/decimator/CIC/sim/tb_cic_c_pipe.fdo 1.2: + * radio/decimator/CIC/sim/tb_cic_decim_pipe.fdo 1.2: + * radio/decimator/CIC/sim/tb_cic_i_pipe.fdo 1.2: + * radio/nco/sim/tb_mix_cordic.fdo 1.5: + * radio/nco/sim/tb_nco_cordic.fdo 1.5: + * radio/nco/sim/tb_nco_lut.fdo 1.3: + * radio/nco/src/mix_cordic.vhd 1.5: + * radio/nco/src/nco_lut.vhd 1.3: + * radio/nco/src/nco_lut_dbg.vhd 1.3: + * radio/nco/src/nco_pkg.vhd 1.5: + * radio/nco/src/tb_mix_cordic.vhd 1.7: + * radio/nco/src/tb_nco_cordic.vhd 1.7: + * radio/nco/src/tb_nco_lut.vhd 1.5: + * radio/nco/src/wavelut.vhd 1.3: + * radio/nco/src/waverom_dual.vhd 1.3: + - uses ieee_proposed.fixed_pkg + + * radio/decimator/CIC/src/cic_c_pipe.vhd 1.2: + * radio/decimator/CIC/src/cic_i_pipe.vhd 1.2: + * radio/decimator/CIC/src/syn_cic_c_pipe.vhd 1.2: + * radio/decimator/CIC/src/syn_cic_i_pipe.vhd 1.2: + * radio/decimator/CIC/src/tb_cic_c_pipe.vhd 1.2: + * radio/decimator/CIC/src/tb_cic_i_pipe.vhd 1.2: + - combine in/out_width to max_width + - uses ieee_proposed.fixed_pkg + + * radio/ddc/src/ddc.vhd 1.2: + * radio/ddc/src/syn_ddc.vhd 1.2: + * radio/ddc/src/tb_ddc.vhd 1.2: + * radio/decimator/CIC/src/cic_decim_pipe.vhd 1.2: + * radio/decimator/CIC/src/tb_cic_decim_pipe.vhd 1.2: + - uses ieee_proposed.fixed_pkg + - din scaled to more fraction precision at integrator input. + Number of integer bits are the same as din + - min_gain intrduced (reduces complexity of barrel shifter). + Din always constant scaled by min_gain. + + * radio/ddc/src/ddc.vhd 1.3: + * radio/ddc/src/syn_ddc.vhd 1.3: + * radio/ddc/src/tb_ddc.vhd 1.3: + * radio/decimator/CIC/src/cic_decim_pipe.vhd 1.4: + * radio/decimator/CIC/src/tb_cic_decim_pipe.vhd 1.3: + - Ratio and gain are set at synthesis time (simpler) + +2008-12-29 Jens + * radio/ddc/sim/tb_ddc.fdo 1.1: + * radio/ddc/sim/tb_ddc.wdo 1.1: + * radio/ddc/sim/tb_results.m 1.1: + * radio/ddc/src/ddc.vhd 1.1: + * radio/ddc/src/syn_ddc.vhd 1.1: + * radio/ddc/src/tb_ddc.vhd 1.1: + * radio/decimator/CIC/sim/tb_cic_c_pipe.fdo 1.1: + * radio/decimator/CIC/sim/tb_cic_c_pipe.wdo 1.1: + * radio/decimator/CIC/sim/tb_cic_decim_pipe.fdo 1.1: + * radio/decimator/CIC/sim/tb_cic_decim_pipe.wdo 1.1: + * radio/decimator/CIC/sim/tb_cic_i_pipe.fdo 1.1: + * radio/decimator/CIC/sim/tb_cic_i_pipe.wdo 1.1: + * radio/decimator/CIC/src/cic_c_pipe.vhd 1.1: + * radio/decimator/CIC/src/cic_decim_pipe.vhd 1.1: + * radio/decimator/CIC/src/cic_i_pipe.vhd 1.1: + * radio/decimator/CIC/src/syn_cic_c_pipe.vhd 1.1: + * radio/decimator/CIC/src/syn_cic_i_pipe.vhd 1.1: + * radio/decimator/CIC/src/tb_cic_c_pipe.vhd 1.1: + * radio/decimator/CIC/src/tb_cic_decim_pipe.vhd 1.1: + * radio/decimator/CIC/src/tb_cic_i_pipe.vhd 1.1: + - Intital revision + +2008-12-28 Jens + * radio/nco/src/mix_cordic.vhd 1.4: + * radio/nco/src/tb_nco_cordic.vhd 1.4: + * radio/nco/src/tb_nco_lut.vhd 1.3: + - Minor changes + + * radio/nco/sim/tb_mix_cordic.fdo 1.4: + * radio/nco/sim/tb_mix_cordic.wdo 1.4: + * radio/nco/sim/tb_mix_cordic.wdo 1.5: + * radio/nco/sim/tb_nco_cordic.fdo 1.4: + * radio/nco/sim/tb_nco_cordic.wdo 1.2: + * radio/nco/sim/tb_nco_cordic.wdo 1.3: + * radio/nco/src/mix_cordic.vhd 1.3: + * radio/nco/src/mix_cordic_dbg.vhd 1.3: + * radio/nco/src/nco_cordic.vhd 1.5: + * radio/nco/src/nco_cordic_dbg.vhd 1.3: + * radio/nco/src/nco_pkg.vhd 1.4: + * radio/nco/src/tb_mix_cordic.vhd 1.6: + * radio/nco/src/tb_nco_cordic.vhd 1.6: + - Cleaned up + + * radio/nco/src/nco_cordic.vhd 1.3: + - added generic for fractional number of bits + + * radio/nco/src/nco_pkg.vhd 1.3: + - moved common functions to fixed_util_pkg + + * radio/nco/sim/tb_mix_results.m 1.2: + - added CIC-decimator + + * radio/nco/src/mix_cordic.vhd 1.1: + - Intital revision + + * radio/cordic/src/cordic_pipe_post.vhd 1.2: + * radio/cordic/src/cordic_pipe_pre.vhd 1.2: + * radio/cordic/src/cordic_pipe_stage.vhd 1.2: + * radio/cordic/src/cordic_pipe_top.vhd 1.4: + * radio/cordic/src/cordic_pkg.vhd 1.3: + * radio/nco/sim/tb_mix_cordic.fdo 1.3: + * radio/nco/sim/tb_nco_cordic.fdo 1.3: + * radio/nco/sim/tb_nco_lut.fdo 1.2: + * radio/nco/src/mix_cordic.vhd 1.2: + * radio/nco/src/nco_cordic.vhd 1.4: + * radio/nco/src/nco_lut.vhd 1.2: + * radio/nco/src/nco_lut_dbg.vhd 1.2: + * radio/nco/src/tb_mix_cordic.vhd 1.5: + * radio/nco/src/tb_nco_cordic.vhd 1.5: + * radio/nco/src/tb_nco_lut.vhd 1.4: + * radio/nco/src/wavelut.vhd 1.2: + * radio/nco/src/waverom_dual.vhd 1.2: + - uses now fixed_util_pkg for common functions + + * radio/nco/sim/tb_mix_cordic.fdo 1.2: + * radio/nco/src/tb_mix_cordic.vhd 1.4: + - use now non-debug-versions (NCO, MIX) for TB + + * radio/nco/sim/tb_nco_cordic.fdo 1.2: + * radio/nco/src/tb_nco_cordic.vhd 1.3: + - use now non-debug-versions (NCO) for TB + +2008-12-22 Jens + * radio/nco/sim/tb_mix_cordic.wdo 1.2: + * radio/nco/sim/tb_mix_cordic.wdo 1.3: + * radio/nco/src/tb_mix_cordic.vhd 1.3: + - Minor changes + + * radio/nco/src/mix_cordic_dbg.vhd 1.2: + * radio/nco/src/nco_cordic_dbg.vhd 1.2: + * radio/nco/src/tb_mix_cordic.vhd 1.2: + * radio/nco/src/tb_nco_cordic.vhd 1.2: + - added generic for fractional number of bits + +2008-12-21 Jens + * radio/cordic/src/cordic_pkg.vhd 1.2: + * radio/nco/src/tb_nco_lut.vhd 1.2: + - Minor changes + + * radio/nco/src/nco_pkg.vhd 1.2: + - added debug_mix_t + + * radio/nco/sim/tb_nco.fdo 1.2: + * radio/nco/sim/tb_nco.wdo 1.2: + * radio/nco/src/nco.vhd 1.2: + * radio/nco/src/nco_cordic.vhd 1.2: + * radio/nco/src/nco_dbg.vhd 1.2: + * radio/nco/src/tb_nco.vhd 1.2: + - Cleaned up + + * radio/cordic/src/cordic_pipe_top.vhd 1.2: + - fixed valid_out signal for gain_corr=disabled + + * radio/cordic/eval_cordic.m 1.1: + * radio/cordic/sim/eval_cordic.m 1.1: + * radio/cordic/sim/tb_cordic_pipe_top.fdo 1.1: + * radio/cordic/sim/tb_cordic_pipe_top.wdo 1.1: + * radio/cordic/sim/tb_cordic_top.fdo 1.1: + * radio/cordic/sim/tb_cordic_top.wdo 1.1: + * radio/cordic/sim/tb_results.m 1.1: + * radio/cordic/src/cordic_pipe_post.vhd 1.1: + * radio/cordic/src/cordic_pipe_pre.vhd 1.1: + * radio/cordic/src/cordic_pipe_stage.vhd 1.1: + * radio/cordic/src/cordic_pipe_top.vhd 1.1: + * radio/cordic/src/cordic_pkg.vhd 1.1: + * radio/cordic/src/cordic_rom.vhd 1.1: + * radio/cordic/src/cordic_stage.vhd 1.1: + * radio/cordic/src/cordic_stage_post.vhd 1.1: + * radio/cordic/src/cordic_stage_pre.vhd 1.1: + * radio/cordic/src/cordic_top.vhd 1.1: + * radio/cordic/src/tb_cordic_pipe_top.vhd 1.1: + * radio/cordic/src/tb_cordic_top.vhd 1.1: + * radio/nco/sim/tb_mix_cordic.fdo 1.1: + * radio/nco/sim/tb_mix_cordic.wdo 1.1: + * radio/nco/sim/tb_mix_results.m 1.1: + * radio/nco/sim/tb_nco_cordic.fdo 1.1: + * radio/nco/sim/tb_nco_cordic.wdo 1.1: + * radio/nco/src/mix_cordic_dbg.vhd 1.1: + * radio/nco/src/nco_cordic.vhd 1.1: + * radio/nco/src/nco_cordic_dbg.vhd 1.1: + * radio/nco/src/tb_mix_cordic.vhd 1.1: + * radio/nco/src/tb_nco_cordic.vhd 1.1: + - Intital revision + + * radio/cordic/src/cordic_pipe_top.vhd 1.3: + - changed z-range default to 1.0 + + * radio/nco/sim/tb_nco_lut.fdo 1.1: + * radio/nco/sim/tb_nco_lut.wdo 1.1: + * radio/nco/src/nco_lut.vhd 1.1: + * radio/nco/src/nco_lut_dbg.vhd 1.1: + * radio/nco/src/tb_nco_lut.vhd 1.1: + - renamed + + * radio/nco/sim/tb_nco_results.m 1.2: + - reduced lower spur boundary + +2008-11-05 Jens + * CPUs/MIPS/src/core/mips_cop.vhd 1.4: + - added Tpd to 'dout' for sim + +2008-11-01 Jens + * ac97_ctrl/sim/tb_ac97_wb.fdo 1.1: + * ac97_ctrl/sim/tb_ac97_wb.wdo 1.1: + * ac97_ctrl/sim/tb_ac_in.fdo 1.1: + * ac97_ctrl/sim/tb_ac_in.wdo 1.1: + * ac97_ctrl/sim/tb_ac_io.fdo 1.1: + * ac97_ctrl/sim/tb_ac_io.wdo 1.1: + * ac97_ctrl/sim/tb_ac_out.fdo 1.1: + * ac97_ctrl/sim/tb_ac_out.wdo 1.1: + * ac97_ctrl/src/core/ac97_wb.vhd 1.1: + * ac97_ctrl/src/core/ac_in.vhd 1.1: + * ac97_ctrl/src/core/ac_io.vhd 1.1: + * ac97_ctrl/src/core/ac_out.vhd 1.1: + * ac97_ctrl/src/tb_ac97_wb.vhd 1.1: + * ac97_ctrl/src/tb_ac_in.vhd 1.1: + * ac97_ctrl/src/tb_ac_io.vhd 1.1: + * ac97_ctrl/src/tb_ac_out.vhd 1.1: + - Intital revision + +2008-10-26 Jens + * CPUs/MIPS/todo.txt 1.1: + - Intital revision + + * CPUs/MIPS/sim/compile_simprim.do 1.2: + * CPUs/MIPS/sim/compile_unisim.do 1.2: + * SDRAM/ddr_sdr_v1_4/sim/compile_simprim.do 1.2: + * SDRAM/ddr_sdr_v1_4/sim/compile_unisim.do 1.2: + * SDRAM/ddr_sdr_v1_5/sim/compile_simprim.do 1.2: + * SDRAM/ddr_sdr_v1_5/sim/compile_unisim.do 1.2: + - Cleaned up + + * CPUs/MIPS/sim/tb_mips_muldiv.fdo 1.2: + * CPUs/MIPS/sim/tb_mips_muldiv.wdo 1.3: + * CPUs/MIPS/src/tb_mips_muldiv.vhd 1.2: + * filter/src/fir_parallel.vhd 1.2: + * filter/src/fir_parallel_pkg.vhd 1.2: + * filter/src/tb_fir_parallel.vhd 1.2: + * filter/src/tb_fir_parallel.vhd 1.3: + * filter/src/tb_fir_parallel.vhd 1.4: + * filter/src/tb_fir_stage.vhd 1.2: + - fixed some bugs + +2008-10-25 Jens + * CPUs/MIPS/src/core/mips_dcache.vhd 1.8: + - Removed dirty-bit which is not needed by Direct-Mapped Cache + + * VGA_ctrl/sim/tb_vga_frontend.wdo 1.2: + * VGA_ctrl/src/tb_vga_frontend.vhd 1.3: + - Minor changes + + * VGA_ctrl/src/dpram.vhd 1.2: + * VGA_ctrl/src/linefifo.vhd 1.2: + - Cleaned up + + * CPUs/MIPS/src/core/mips_cop.vhd 1.3: + - Removed DEADBEEF-garbage + + * CPUs/MIPS/src/core/mips_biu.vhd 1.15: + - added generics for cache sizes + + * VGA_ctrl/src/char_gen.vhd 1.2: + - using now dpram_1w1r + + * VGA_ctrl/src/vga_backend.vhd 1.3: + - removed delay at color output. Fixes image problems. + + * CPUs/MIPS/src/core/mips_top.vhd 1.5: + - using bui-generics for cache sizes + + * CPUs/MIPS/syn/ise101/mips_top.prj 1.1: + * CPUs/MIPS/syn/ise101/mips_top_vhdl.prj 1.1: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend64_wb.fdo 1.1: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend64_wb.wdo 1.1: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend64_wb.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend64_wb.vhd 1.1: + * VGA_ctrl/sim/tb_vga_frontend64.fdo 1.1: + * VGA_ctrl/sim/tb_vga_frontend64.wdo 1.1: + * VGA_ctrl/src/tb_vga_frontend64.vhd 1.1: + * VGA_ctrl/src/vga_frontend64.vhd 1.1: + - Intital revision + + * VGA_ctrl/src/vga_types.vhd 1.3: + - added conversion functions unsigned <=> color_t + + * VGA_ctrl/sim/tb_vga_frontend.fdo 1.2: + -Removed linefifo.vhd and dpram.vhd + - Uses now lib/FIFO/fifo_async.vhd + + * VGA_ctrl/src/vga_frontend.vhd 1.2: + - Removed linefifo + - Uses now lib/FIFO/fifo_async.vhd + + * FIFO/src/fifo_async_ctrl.vhd 1.2: + - Bugfix: changed 'ptr_r' from 'bcnt_r' to 'bnxt_r' to prevent + read delay when FIFO is read (re = 1) + +2008-10-24 Jens + * FIFO/src/fifo_async.vhd 1.1: + - Intital revision + + * FIFO/src/fifo_sync.vhd 1.3: + * VGA_ctrl/src/tb_vga_frontend.vhd 1.2: + - Cleaned up + +2008-10-23 Jens + * CPUs/MIPS/sim/tb_mips_muldiv.wdo 1.2: + - Minor changes + + * CPUs/JCpu/sim/ModelSim SE .lnk 1.1: + * CPUs/MIPS/sim/ModelSim SE .lnk 1.1: + - Intital revision + + * CPUs/MIPS/sim/tb_eval_muldiv.fdo 1.2: + * CPUs/MIPS/sim/tb_eval_muldiv.wdo 1.2: + * CPUs/MIPS/src/mips_muldiv.vhd 1.2: + * CPUs/MIPS/src/tb_eval_muldiv.vhd 1.2: + - Cleaned up + + * SDRAM/ddr_sdr_v1_5/sim/ModelSim SE .lnk 1.2: + * SSRAM/sim/ModelSim SE .lnk 1.2: + * VGA_ctrl/sim/ModelSim SE .lnk 1.2: + * misc/sim/ModelSim SE .lnk 1.2: + - Using MODELSIM_HOME environment variable + +2008-10-20 Jens + * SSRAM/sim/ModelSim SE .lnk 1.1: + * SSRAM/sim/tb_ssram_frontend_wb.fdo 1.1: + * SSRAM/sim/tb_ssram_frontend_wb.wdo 1.1: + * SSRAM/src/CY7C1354B.vhd 1.1: + * SSRAM/src/package_utility.vhd 1.1: + * SSRAM/src/ssram_frontend_wb.vhd 1.1: + * SSRAM/src/tb_ssram_frontend_wb.vhd 1.1: + * VGA_ctrl/sim/ModelSim SE .lnk 1.1: + * misc/bbfifo.vhd 1.1: + * misc/gpio_wb.vhd 1.1: + * misc/ram_sim.vhd 1.1: + * misc/ram_wb.vhd 1.1: + * misc/rom_sim.vhd 1.1: + * misc/rom_wb.vhd 1.1: + * misc/sim/ModelSim SE .lnk 1.1: + * misc/sim/tb_bbfifo.fdo 1.1: + * misc/sim/tb_bbfifo.wdo 1.1: + * misc/sim/tb_ram_wb.fdo 1.1: + * misc/sim/tb_ram_wb.wdo 1.1: + * misc/sim/tb_rom_wb.fdo 1.1: + * misc/sim/tb_rom_wb.wdo 1.1: + * misc/tb_bbfifo.vhd 1.1: + * misc/tb_ram_wb.vhd 1.1: + * misc/tb_rom_wb.vhd 1.1: + - Intital revision + +2008-10-19 Jens + * VGA_ctrl/src/vga_types.vhd 1.2: + Minor changes + + * VGA_ctrl/sim/tb_vga_frontend.fdo 1.1: + * VGA_ctrl/sim/tb_vga_frontend.wdo 1.1: + * VGA_ctrl/src/tb_vga_frontend.vhd 1.1: + * VGA_ctrl/src/vga_frontend.vhd 1.1: + - Intital revision + + * VGA_ctrl/src/vga_backend.vhd 1.2: + - Removed linefifo and clockgen (=> frontend and top) + +2008-10-18 Jens + * SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd 1.2: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.7: + Minor changes + + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.4: + - Cleaned up + + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo 1.3: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.wdo 1.3: + * SDRAM/ddr_sdr_v1_5/src/sdram_config.vhd 1.2: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.3: + - using now 64-bit SDR interface (2 SDRAMS) + + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl.vhd 1.2: + - introduced per-bank activation (avoids multiple activations on same bank) + - some other improvements + +2008-10-17 Jens + * CPUs/MIPS/src/core/mips_biu.vhd 1.14: + - Removed registered CYC_O (didn't work) + + * FIFO/src/fifo_sync_dist.vhd 1.1: + - Intital revision + + * CPUs/MIPS/src/core/mips_biu.vhd 1.12: + - Registered CYC_O + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.7: + * CPUs/MIPS/src/core/mips_icache.vhd 1.4: + - Shortened BUS-cycle by one clock + + * FIFO/src/fifo_sync.vhd 1.2: + - Removed distributed DPRAM reference + + * CPUs/MIPS/src/core/mips_biu.vhd 1.13: + - Shortened read cycles + - Minor improvements + +2008-10-15 Jens + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.6: + Simplified + +2008-10-14 Jens + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.5: + - Uses now full capacity of SDRAM (64-Bit interface on ML-402) + - Removed read data mask + + * CPUs/MIPS/src/core/mips_biu.vhd 1.11: + Minor changes + + * SDRAM/ddr_sdr_v1_5/src/ddr_phy_virtex4.vhd 1.2: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.2: + - Removed read data mask + + * SDRAM/ddr_sdr_v1_5/src/fifo_sync.vhd 1.3: + - Moved to lib/FIFO + + * FIFO/src/fifo_sync.vhd 1.1: + - Intital revision + - Moved from SDRAM v1.5 to here + +2008-10-12 Jens + * misc/async_port_wb.vhd 1.3: + Registered rdy (better timing) + + * FIFO/src/fifo_sync_ctrl.vhd 1.2: + - Output pre_empty and pre_full for safer DPRAM control + + * CPUs/MIPS/src/core/mips_biu.vhd 1.10: + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.7: + * CPUs/MIPS/src/core/mips_top.vhd 1.4: + - Changed we to be + - Changed r_wn to we + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.6: + - Simplfied (better timing) + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.5: + Cleaned up + +2008-10-11 Jens + * CPUs/MIPS/src/core/mips_biu.vhd 1.9: + Bug fix: Uncached read and buffer write in different state + + * misc/async_port_wb.vhd 1.2: + Bug fix: Address and data latch only if ready + +2008-10-10 Jens + * CPUs/MIPS/src/core/mips_biu.vhd 1.8: + Added bus fifo and write fifo + + * misc/async_port.vhd 1.3: + * misc/hpi_port.vhd 1.2: + deleted + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.4: + Added instant RAW avoidance + + * SDRAM/ddr_sdr_v1_5/src/fifo_sync.vhd 1.2: + - Inhibit RAM write if FIFO is full + - Inhibit update of output if last word is read + + * misc/async_port_wb.vhd 1.1: + * misc/clockgen_virtex4.vhd 1.1: + * uart/uart_wb.vhd 1.1: + Intital revision + + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.4: + * misc/async_port.vhd 1.2: + Removed ACK for J-Bus writes + +2008-10-09 Jens + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.6: + - Added bus error signals for IBE/DBE generation + + * CPUs/MIPS/src/core/mips_biu.vhd 1.6: + - Added Bus timeout detection + - STB_O, ADDR_O registered to output when SRDY + + * CPUs/MIPS/src/core/mips_dcache.vhd 1.3: + * CPUs/MIPS/src/core/mips_icache.vhd 1.3: + - STB_O now deasserts only if SRDY active (fixes bus freezes + during heavy traffic) + + * CPUs/MIPS/src/core/mips_top.vhd 1.3: + - Added bus error signals + + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.3: + Cleaned up + + * CPUs/MIPS/src/core/mips_biu.vhd 1.7: + Minor changes + +2008-10-08 Jens + * CPUs/MIPS/src/core/mips_biu.vhd 1.5: + Added data mask support + + * CPUs/MIPS/src/core/mips_cop.vhd 1.2: + Masked IPs are not shown in CR + +2008-10-07 Jens + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo 1.2: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.wdo 1.2: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.2: + Minor changes + + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.2: + - Registered ACK + - 32bit Host I/F + + * CPUs/MIPS/src/core/mips_biu.vhd 1.4: + * CPUs/MIPS/src/core/mips_dcache.vhd 1.2: + * CPUs/MIPS/src/core/mips_icache.vhd 1.2: + * CPUs/MIPS/src/core/mips_top.vhd 1.2: + Introduced J-Bus + +2008-10-02 Jens + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl.vhd 1.2: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_fifo.vhd 1.2: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_lin_r_rand_w.vhd 1.2: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_lin_w_rand_r.vhd 1.2: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_rand_addr.vhd 1.2: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_rand_rw.vhd 1.2: + Added data mask support + + * SDRAM/ddr_sdr_v1_4/src/ddr_phy_virtex4.vhd 1.2: + * SDRAM/ddr_sdr_v1_4/src/sdram_ctrl_frontend.vhd 1.2: + * SDRAM/ddr_sdr_v1_4/src/sdram_ctrl_top.vhd 1.2: + Added data mask (read) support + + * SDRAM/ddr_sdr_v1_5/sim/ModelSim SE .lnk 1.1: + * SDRAM/ddr_sdr_v1_5/sim/compile_simprim.do 1.1: + * SDRAM/ddr_sdr_v1_5/sim/compile_unisim.do 1.1: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.fdo 1.1: + * SDRAM/ddr_sdr_v1_5/sim/tb_sdram_ctrl_frontend_wb.wdo 1.1: + * SDRAM/ddr_sdr_v1_5/src/ddr_phy_virtex4.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/fifo_sync.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/mt46v16m16.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/reset_virtex4.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/sdram_cmd.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/sdram_config.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_frontend_wb.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/sdram_ctrl_top.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/sdram_types.vhd 1.1: + * SDRAM/ddr_sdr_v1_5/src/tb_sdram_ctrl_frontend_wb.vhd 1.1: + Intital revision + +2008-09-21 Jens + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.5: + Minor changes + + * CPUs/MIPS/src/core/mips_biu.vhd 1.3: + Cleaned up + + * misc/async_port.vhd 1.1: + Intital revision + +2008-09-20 Jens + * CPUs/MIPS/src/core/mips_biu.vhd 1.2: + Memory write now waits for completion (bus_rdy) + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.3: + Branch: check op_a for equaliity against R0 instead testing of + explicitly against zero + + * CPUs/MIPS/src/core/mips_bcu.vhd 1.2: + Removed zero check + + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.4: + Minor changes to satisfy timing + + * CPUs/MIPS/src/core/mips_types.vhd 1.2: + Removed z-flag from bcu_t + +2008-09-12 Jens + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.2: + BCU_op update if not ex.stall + +2008-09-04 Jens + * misc/hpi_port.vhd 1.1: + Initial import + +2008-08-25 Jens + * CPUs/MIPS/tools/make 1.4: + Removed + + * CPUs/MIPS/tools/Makefile 1.1: + * CPUs/MIPS/tools/make.sh 1.1: + Initial import + +2008-08-23 Jens + * CPUs/MIPS/tools/make 1.3: + Minor changes + + * CPUs/JCpu/asm/dctest.jsm 1.1.1.1: + * CPUs/JCpu/asm/dctest.tcl 1.1.1.1: + * CPUs/JCpu/asm/itest.jsm 1.1.1.1: + * CPUs/JCpu/asm/itest.tcl 1.1.1.1: + * CPUs/JCpu/asm/make 1.1.1.1: + * CPUs/JCpu/asm/mul8x8.jsm 1.1.1.1: + * CPUs/JCpu/asm/mul8x8.tcl 1.1.1.1: + * CPUs/JCpu/asm/reti_issue.jsm 1.1.1.1: + * CPUs/JCpu/asm/reti_issue.tcl 1.1.1.1: + * CPUs/JCpu/doc/block_diagram.png 1.1.1.1: + * CPUs/JCpu/doc/memory_map.png 1.1.1.1: + * CPUs/JCpu/gpl-3.0.txt 1.1.1.1: + * CPUs/JCpu/sim/tb_cpu.fdo 1.1.1.1: + * CPUs/JCpu/sim/tb_cpu.wdo 1.1.1.1: + * CPUs/JCpu/sim/tb_cpu_embedded.fdo 1.1.1.1: + * CPUs/JCpu/sim/tb_cpu_embedded.wdo 1.1.1.1: + * CPUs/JCpu/sim/tb_cpu_itest.fdo 1.1.1.1: + * CPUs/JCpu/sim/tb_cpu_itest.wdo 1.1.1.1: + * CPUs/JCpu/sim/tb_cpu_reti_issue.fdo 1.1.1.1: + * CPUs/JCpu/sim/tb_cpu_reti_issue.wdo 1.1.1.1: + * CPUs/JCpu/sim/tb_mul8x8.fdo 1.1.1.1: + * CPUs/JCpu/sim/tb_mul8x8.wdo 1.1.1.1: + * CPUs/JCpu/src/core/alu.vhd 1.1.1.1: + * CPUs/JCpu/src/core/chipram.vhd 1.1.1.1: + * CPUs/JCpu/src/core/chipreg.vhd 1.1.1.1: + * CPUs/JCpu/src/core/cpu.vhd 1.1.1.1: + * CPUs/JCpu/src/core/cpu_pkg.vhd 1.1.1.1: + * CPUs/JCpu/src/core/dpath_ctrl.vhd 1.1.1.1: + * CPUs/JCpu/src/core/int_ctrl.vhd 1.1.1.1: + * CPUs/JCpu/src/core/pc.vhd 1.1.1.1: + * CPUs/JCpu/src/core/reg_dual.vhd 1.1.1.1: + * CPUs/JCpu/src/core/stack_ctrl.vhd 1.1.1.1: + * CPUs/JCpu/src/cpu_embedded.vhd 1.1.1.1: + * CPUs/JCpu/src/dctest_irom.vhdl 1.1.1.1: + * CPUs/JCpu/src/dctest_irom_ld.vhdl 1.1.1.1: + * CPUs/JCpu/src/dctest_xrom.vhdl 1.1.1.1: + * CPUs/JCpu/src/dctest_xrom_ld.vhdl 1.1.1.1: + * CPUs/JCpu/src/itest_irom.vhdl 1.1.1.1: + * CPUs/JCpu/src/itest_irom_ld.vhdl 1.1.1.1: + * CPUs/JCpu/src/itest_xrom.vhdl 1.1.1.1: + * CPUs/JCpu/src/itest_xrom_ld.vhdl 1.1.1.1: + * CPUs/JCpu/src/mul8x8_irom.vhdl 1.1.1.1: + * CPUs/JCpu/src/mul8x8_irom_ld.vhdl 1.1.1.1: + * CPUs/JCpu/src/mul8x8_xrom.vhdl 1.1.1.1: + * CPUs/JCpu/src/mul8x8_xrom_ld.vhdl 1.1.1.1: + * CPUs/JCpu/src/reti_issue_irom.vhdl 1.1.1.1: + * CPUs/JCpu/src/reti_issue_irom_ld.vhdl 1.1.1.1: + * CPUs/JCpu/src/reti_issue_xrom.vhdl 1.1.1.1: + * CPUs/JCpu/src/reti_issue_xrom_ld.vhdl 1.1.1.1: + * CPUs/JCpu/src/tb_cpu_embedded.vhd 1.1.1.1: + * CPUs/JCpu/src/tb_cpu_itest.vhd 1.1.1.1: + * CPUs/JCpu/syn/ise91/cpu_vhdl.prj 1.1.1.1: + * CPUs/JCpu/tools/eval_scan.rb 1.1.1.1: + * CPUs/JCpu/tools/insrom.rb 1.1.1.1: + * CPUs/JCpu/tools/irom.vhd.tpl 1.1.1.1: + * CPUs/JCpu/tools/irom_ld.vhd.tpl 1.1.1.1: + * CPUs/JCpu/tools/jasm.bak.rb 1.1.1.1: + * CPUs/JCpu/tools/jasm.rb 1.1.1.1: + * CPUs/JCpu/tools/lib/cg.inc.jsm 1.1.1.1: + * CPUs/JCpu/tools/lib/cregs.inc.jsm 1.1.1.1: + * CPUs/JCpu/tools/lib/delays.inc.jsm 1.1.1.1: + * CPUs/JCpu/tools/lib/lcd.inc.jsm 1.1.1.1: + * CPUs/JCpu/tools/lib/mul8x8.inc.jsm 1.1.1.1: + * CPUs/JCpu/tools/lib/uart.inc.jsm 1.1.1.1: + * CPUs/JCpu/tools/lib/utils.inc.jsm 1.1.1.1: + * CPUs/JCpu/tools/opc.list 1.1.1.1: + * CPUs/JCpu/tools/regx.rb 1.1.1.1: + * CPUs/JCpu/tools/rom.tcl.tpl 1.1.1.1: + * CPUs/JCpu/tools/templates.rb 1.1.1.1: + * CPUs/JCpu/tools/xrom.vhd.tpl 1.1.1.1: + * CPUs/JCpu/tools/xrom_ld.vhd.tpl 1.1.1.1: + * CPUs/MIPS/sim/compile_simprim.do 1.1.1.1: + * CPUs/MIPS/sim/compile_unisim.do 1.1.1.1: + * CPUs/MIPS/sim/tb_eval_muldiv.fdo 1.1.1.1: + * CPUs/MIPS/sim/tb_eval_muldiv.wdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_embedded.fdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_embedded.wdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_embedded_syn.fdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_embedded_syn.tdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_embedded_syn.wdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_muldiv.fdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_muldiv.ndo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_muldiv.sdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_muldiv.wdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_top.fdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_top.mdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_top.mwdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_top.sdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_top.wdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_top_syn.mdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_top_syn.tdo 1.1.1.1: + * CPUs/MIPS/sim/tb_mips_top_syn.wdo 1.1.1.1: + * CPUs/MIPS/src/core/mips_alu.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_bcu.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_biu.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_cop.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_dcache.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_icache.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_idecode_rom.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_instr.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_muldiv.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_pipeline.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_reg.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_shifter.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_top.vhd 1.1.1.1: + * CPUs/MIPS/src/core/mips_types.vhd 1.1.1.1: + * CPUs/MIPS/src/fibonacci.ROM_ld.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_hello.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test1.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test2.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test3.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test4.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test5.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test6.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test_addsub.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test_slt.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test_slti.vhd 1.1.1.1: + * CPUs/MIPS/src/irom_test_sub.vhd 1.1.1.1: + * CPUs/MIPS/src/mips_embedded.vhd 1.1.1.1: + * CPUs/MIPS/src/mips_embedded_syn.vhd 1.1.1.1: + * CPUs/MIPS/src/mips_muldiv.vhd 1.1.1.1: + * CPUs/MIPS/src/ram.vhd 1.1.1.1: + * CPUs/MIPS/src/ram_ld.vhd 1.1.1.1: + * CPUs/MIPS/src/ram_sim.vhd 1.1.1.1: + * CPUs/MIPS/src/rmd160_test.ROM_ld.vhd 1.1.1.1: + * CPUs/MIPS/src/tb_eval_muldiv.vhd 1.1.1.1: + * CPUs/MIPS/src/tb_mips_embedded.vhd 1.1.1.1: + * CPUs/MIPS/src/tb_mips_embedded_syn.vhd 1.1.1.1: + * CPUs/MIPS/src/tb_mips_muldiv.vhd 1.1.1.1: + * CPUs/MIPS/src/tb_mips_top.vhd 1.1.1.1: + * CPUs/MIPS/src/testbench.ROM_ld.vhd 1.1.1.1: + * CPUs/MIPS/tools/insrom.rb 1.1.1.1: + * CPUs/MIPS/tools/irom.vhd.tpl 1.1.1.1: + * CPUs/MIPS/tools/irom_ld.vhd.tpl 1.1.1.1: + * CPUs/MIPS/tools/make 1.1.1.1: + * CPUs/MIPS/tools/rom.tcl.tpl 1.1.1.1: + * CPUs/MIPS/tools/src/ramgen.c 1.1.1.1: + * CPUs/MIPS/tools/src/romgen.c 1.1.1.1: + * FIFO/sim/tb_async_fifo_ctrl.fdo 1.1: + * FIFO/sim/tb_async_fifo_ctrl.wdo 1.1: + * FIFO/sim/tb_gray_counter.fdo 1.1: + * FIFO/sim/tb_gray_counter.wdo 1.1: + * FIFO/sim/tb_sync_fifo_ctrl.fdo 1.1: + * FIFO/sim/tb_sync_fifo_ctrl.wdo 1.1: + * FIFO/src/dpram.vhd 1.1: + * FIFO/src/fifo_async_ctrl.vhd 1.1: + * FIFO/src/fifo_ctrl_pkg.vhd 1.1: + * FIFO/src/fifo_sync_ctrl.vhd 1.1: + * FIFO/src/gray_counter.vhd 1.1: + * FIFO/src/tb_async_fifo_ctrl.vhd 1.1: + * FIFO/src/tb_gray_counter.vhd 1.1: + * FIFO/src/tb_sync_fifo_ctrl.vhd 1.1: + * PCK_FIO-1.16/PCK_FIO.html 1.1: + * PCK_FIO-1.16/PCK_FIO.out.gold 1.1: + * PCK_FIO-1.16/PCK_FIO.vhd 1.1: + * PCK_FIO-1.16/README 1.1: + * PCK_FIO-1.16/TB_PCK_FIO.vhd 1.1: + * PCK_FIO-2002.7/CHANGES 1.1: + * PCK_FIO-2002.7/PCK_FIO.html 1.1: + * PCK_FIO-2002.7/PCK_FIO.out.gold 1.1: + * PCK_FIO-2002.7/PCK_FIO_1987.vhd 1.1: + * PCK_FIO-2002.7/PCK_FIO_1987_BODY.vhd 1.1: + * PCK_FIO-2002.7/PCK_FIO_1993.vhd 1.1: + * PCK_FIO-2002.7/PCK_FIO_1993_BODY.vhd 1.1: + * PCK_FIO-2002.7/README 1.1: + * PCK_FIO-2002.7/TB_PCK_FIO_1987.vhd 1.1: + * PCK_FIO-2002.7/TB_PCK_FIO_1993.vhd 1.1: + * PCK_FIO-2002.7/msMakefile.TBE_PCK_FIO_TB.1987 1.1: + * PCK_FIO-2002.7/msMakefile.TBE_PCK_FIO_TB.1993 1.1: + * SDRAM/ddr_sdr_v1_4/ise9/sdram_ctrl_top_vhdl.prj 1.1: + * SDRAM/ddr_sdr_v1_4/sim/compile_simprim.do 1.1: + * SDRAM/ddr_sdr_v1_4/sim/compile_unisim.do 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl.fdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl.wdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_fifo.fdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_fifo.wdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_lin_r_rand_w.fdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_lin_r_rand_w.wdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_lin_w_rand_r.fdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_lin_w_rand_r.wdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_rand_addr.fdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_rand_addr.wdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_rand_rw.fdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdr_ctrl_rand_rw.wdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdram_ctrl_frontend.fdo 1.1: + * SDRAM/ddr_sdr_v1_4/sim/tb_sdram_ctrl_frontend.wdo 1.1: + * SDRAM/ddr_sdr_v1_4/src/clockgen_virtex4.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/ddr_phy_virtex4.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/fifo_sync.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/mt46v16m16.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/reset_virtex4.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/sdram_cmd.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/sdram_config.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/sdram_ctrl.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/sdram_ctrl_frontend.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/sdram_ctrl_top.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/sdram_types.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_fifo.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_lin_r_rand_w.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_lin_w_rand_r.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_rand_addr.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/tb_sdr_ctrl_rand_rw.vhd 1.1: + * SDRAM/ddr_sdr_v1_4/src/tb_sdram_ctrl_frontend.vhd 1.1: + * VGA_ctrl/src/char_gen.vhd 1.1: + * VGA_ctrl/src/clkgen_virtex4.vhd 1.1: + * VGA_ctrl/src/dpram.vhd 1.1: + * VGA_ctrl/src/fonts/Fixedsys_8x15.bff 1.1: + * VGA_ctrl/src/fonts/Fixedsys_8x16.bff 1.1: + * VGA_ctrl/src/fonts/Fixedsys_9x16.bff 1.1: + * VGA_ctrl/src/fonts/System_16x16.bff 1.1: + * VGA_ctrl/src/fonts/char_rom_c64.vhd 1.1: + * VGA_ctrl/src/fonts/char_rom_data.vhd 1.1: + * VGA_ctrl/src/fonts/char_rom_datasoft.vhd 1.1: + * VGA_ctrl/src/fonts/char_rom_demo_maker_m.vhd 1.1: + * VGA_ctrl/src/fonts/char_rom_fixedsys_8x15.vhd 1.1: + * VGA_ctrl/src/fonts/char_rom_fixedsys_8x16.vhd 1.1: + * VGA_ctrl/src/fonts/char_rom_fixedsys_9x16.vhd 1.1: + * VGA_ctrl/src/fonts/char_rom_system_16x16.vhd 1.1: + * VGA_ctrl/src/fonts/char_rom_the_goonies.vhd 1.1: + * VGA_ctrl/src/fonts/make_rom.bat 1.1: + * VGA_ctrl/src/linefifo.vhd 1.1: + * VGA_ctrl/src/vga_backend.vhd 1.1: + * VGA_ctrl/src/vga_sync.vhd 1.1: + * VGA_ctrl/src/vga_timing.vhd 1.1: + * VGA_ctrl/src/vga_types.vhd 1.1: + * filter/sim/eval_lowpass.m 1.1: + * filter/sim/lowpass.m 1.1: + * filter/sim/tb_fir_iterative.fdo 1.1: + * filter/sim/tb_fir_iterative.wdo 1.1: + * filter/sim/tb_fir_parallel 1.1: + * filter/sim/tb_fir_parallel.fdo 1.1: + * filter/sim/tb_fir_parallel.wdo 1.1: + * filter/sim/tb_fir_results.m 1.1: + * filter/sim/tb_fir_stage.fdo 1.1: + * filter/sim/tb_fir_stage.wdo 1.1: + * filter/src/filter_pkg.vhd 1.1: + * filter/src/fir_iterative.vhd 1.1: + * filter/src/fir_iterative_pkg.vhd 1.1: + * filter/src/fir_parallel.vhd 1.1: + * filter/src/fir_parallel_pkg.vhd 1.1: + * filter/src/fir_stage.vhd 1.1: + * filter/src/fir_stage_pkg.vhd 1.1: + * filter/src/tb_fir_iterative.vhd 1.1: + * filter/src/tb_fir_parallel.vhd 1.1: + * filter/src/tb_fir_stage.vhd 1.1: + * fix_std/fix_std.vhd 1.1: + * fix_std/fix_stdb.vhd 1.1: + * fixed/fixed_pkg_c.vhd 1.1: + * fixed_ja/fixed_ja.vhd 1.1: + * fixed_ja/fixed_ja_body.vhd 1.1: + * jasm/cg.inc.jsm 1.1: + * jasm/cregs.inc.jsm 1.1: + * jasm/delays.inc.jsm 1.1: + * jasm/lcd.inc.jsm 1.1: + * jasm/mul8x8.inc.jsm 1.1: + * jasm/uart.inc.jsm 1.1: + * jasm/utils.inc.jsm 1.1: + * misc/debounce.vhd 1.1: + * misc/debounce2.vhd 1.1: + * misc/dpram_1w1r.vhd 1.1: + * misc/dpram_1w1r_dist.vhd 1.1: + * misc/dpram_2w2r.vhd 1.1: + * misc/dpram_2w2r_virtex4.vhd 1.1: + * misc/lcd_port.vhd 1.1: + * misc/oneshot.vhd 1.1: + * misc/pkg_template.vhd 1.1: + * misc/singleshot.vhd 1.1: + * misc/tb_template.vhd 1.1: + * misc/utils_pkg.vhd 1.1: + * radio/mix/sim/tb_mix_cpx.fdo 1.1: + * radio/mix/sim/tb_mix_cpx.wdo 1.1: + * radio/mix/sim/tb_mix_real.fdo 1.1: + * radio/mix/sim/tb_mix_real.wdo 1.1: + * radio/mix/sim/tb_undc_real.fdo 1.1: + * radio/mix/sim/tb_undc_real.wdo 1.1: + * radio/mix/src/mix_cpx.vhd 1.1: + * radio/mix/src/mix_pkg.vhd 1.1: + * radio/mix/src/mix_real.vhd 1.1: + * radio/mix/src/tb_mix_cpx.vhd 1.1: + * radio/mix/src/tb_mix_real.vhd 1.1: + * radio/mix/src/tb_undc_real.vhd 1.1: + * radio/mix/src/undc_real.vhd 1.1: + * radio/nco/sim/tb_nco.fdo 1.1: + * radio/nco/sim/tb_nco.wdo 1.1: + * radio/nco/sim/tb_nco_results.m 1.1: + * radio/nco/src/nco.vhd 1.1: + * radio/nco/src/nco.vhd.bak 1.1: + * radio/nco/src/nco_dbg.vhd 1.1: + * radio/nco/src/nco_pkg.vhd 1.1: + * radio/nco/src/tb_nco.vhd 1.1: + * radio/nco/src/wavelut.vhd 1.1: + * radio/nco/src/waverom_dual.vhd 1.1: + * uart/bbfifo_16x8.vhd 1.1: + * uart/kcuart_rx.vhd 1.1: + * uart/kcuart_tx.vhd 1.1: + * uart/uart_rx.vhd 1.1: + * uart/uart_tx.vhd 1.1: + Initial import + + * CPUs/MIPS/tools/make 1.2: + Added CVS header + diff --git a/lib/Standard/ieee/add/numeric_std_additions.vhdl b/lib/Standard/ieee/add/numeric_std_additions.vhdl new file mode 100644 index 0000000..dce15e4 --- /dev/null +++ b/lib/Standard/ieee/add/numeric_std_additions.vhdl @@ -0,0 +1,2640 @@ +------------------------------------------------------------------------------ +-- "numeric_std_additions" package contains the additions to the standard +-- "numeric_std" package proposed by the VHDL-200X-ft working group. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee.numeric_std.all; +-- use ieee_proposed.numeric_std_additions.all; +-- (this package is independant of "std_logic_1164_additions") +-- Last Modified: $Date: 2006-03-22 16:28:26-05 $ +-- RCS ID: $Id: numeric_std_additions.vhd,v 1.6 2006-03-22 16:28:26-05 l435385 Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use std.textio.all; + +package numeric_std_additions is + -- Id: A.3R + function "+"(L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + -- Result subtype: UNSIGNED(L'RANGE) + -- Result: Similar to A.3 where R is a one bit UNSIGNED + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'RANGE) + -- Result: Similar to A.3 where L is a one bit UNSIGNED + + -- Id: A.4R + function "+"(L : SIGNED; R : STD_ULOGIC) return SIGNED; + -- Result subtype: SIGNED(L'RANGE) + -- Result: Similar to A.4 where R is bit 0 of a non-negative + -- SIGNED + + -- Id: A.4L + function "+"(L : STD_ULOGIC; R : SIGNED) return SIGNED; + -- Result subtype: UNSIGNED(R'RANGE) + -- Result: Similar to A.4 where L is bit 0 of a non-negative + -- SIGNED + -- Id: A.9R + function "-"(L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + -- Result subtype: UNSIGNED(L'RANGE) + -- Result: Similar to A.9 where R is a one bit UNSIGNED + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'RANGE) + -- Result: Similar to A.9 where L is a one bit UNSIGNED + + -- Id: A.10R + function "-"(L : SIGNED; R : STD_ULOGIC) return SIGNED; + -- Result subtype: SIGNED(L'RANGE) + -- Result: Similar to A.10 where R is bit 0 of a non-negative + -- SIGNED + + -- Id: A.10L + function "-"(L : STD_ULOGIC; R : SIGNED) return SIGNED; + -- Result subtype: UNSIGNED(R'RANGE) + -- Result: Similar to A.10 where R is bit 0 of a non-negative + -- SIGNED + + function RESIZE (ARG, SIZE_RES : SIGNED) return SIGNED; + -- size_res version, uses the size of the "size_res" input + -- to resize the output + + function RESIZE (ARG, SIZE_RES : UNSIGNED) return UNSIGNED; + -- size_res version, uses the size of the "size_res" input + -- to resize the output + function TO_UNSIGNED (ARG : NATURAL; SIZE_RES : UNSIGNED) return UNSIGNED; + -- size_res version, uses the size of the "size_res" input + -- to resize the output + function TO_SIGNED (ARG : INTEGER; SIZE_RES : SIGNED) return SIGNED; + -- size_res version, uses the size of the "size_res" input + -- to resize the output + + -- Id: M.2B + -- %%% function "?=" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?/=" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?>" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?>=" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?<" (L, R : UNSIGNED) return std_ulogic; + -- %%% function "?<=" (L, R : UNSIGNED) return std_ulogic; + function \?=\ (L, R : UNSIGNED) return std_ulogic; + function \?/=\ (L, R : UNSIGNED) return std_ulogic; + function \?>\ (L, R : UNSIGNED) return std_ulogic; + function \?>=\ (L, R : UNSIGNED) return std_ulogic; + function \?<\ (L, R : UNSIGNED) return std_ulogic; + function \?<=\ (L, R : UNSIGNED) return std_ulogic; + -- Result subtype: STD_ULOGIC + -- Result: terms compared per STD_LOGIC_1164 intent, + -- returns an 'X' if a metavalue is passed + + -- Id: M.3B + -- %%% function "?=" (L, R : SIGNED) return std_ulogic; + -- %%% function "?/=" (L, R : SIGNED) return std_ulogic; + -- %%% function "?>" (L, R : SIGNED) return std_ulogic; + -- %%% function "?>=" (L, R : SIGNED) return std_ulogic; + -- %%% function "?<" (L, R : SIGNED) return std_ulogic; + -- %%% function "?<=" (L, R : SIGNED) return std_ulogic; + function \?=\ (L, R : SIGNED) return std_ulogic; + function \?/=\ (L, R : SIGNED) return std_ulogic; + function \?>\ (L, R : SIGNED) return std_ulogic; + function \?>=\ (L, R : SIGNED) return std_ulogic; + function \?<\ (L, R : SIGNED) return std_ulogic; + function \?<=\ (L, R : SIGNED) return std_ulogic; + -- Result subtype: std_ulogic + -- Result: terms compared per STD_LOGIC_1164 intent, + -- returns an 'X' if a metavalue is passed + + ----------------------------------------------------------------------------- + -- New/updated funcitons for VHDL-200X fast track + ----------------------------------------------------------------------------- + -- add_carry procedures, to provide a carry in and a carry out + procedure add_carry ( + L, R : in UNSIGNED; + c_in : in STD_ULOGIC; + result : out UNSIGNED; + c_out : out STD_ULOGIC); + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Procedure takes a carry in into the adder, and provides a carry out. + + procedure add_carry ( + L, R : in SIGNED; + c_in : in STD_ULOGIC; + result : out SIGNED; + c_out : out STD_ULOGIC); + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Procedure takes a carry in into the adder, and provides a carry out. + + -- Overloaded functions from "std_logic_1164" + function To_X01 (s : UNSIGNED) return UNSIGNED; + function To_X01 (s : SIGNED) return SIGNED; + + function To_X01Z (s : UNSIGNED) return UNSIGNED; + function To_X01Z (s : SIGNED) return SIGNED; + + function To_UX01 (s : UNSIGNED) return UNSIGNED; + function To_UX01 (s : SIGNED) return SIGNED; + + function Is_X (s : UNSIGNED) return BOOLEAN; + function Is_X (s : SIGNED) return BOOLEAN; + + function "sla" (ARG : SIGNED; COUNT : INTEGER) return SIGNED; + function "sla" (ARG : UNSIGNED; COUNT : INTEGER) return UNSIGNED; + + function "sra" (ARG : SIGNED; COUNT : INTEGER) return SIGNED; + function "sra" (ARG : UNSIGNED; COUNT : INTEGER) return UNSIGNED; + + -- New conversion functions, these drop or add sign bits only + function remove_sign (arg : SIGNED) return UNSIGNED; + function add_sign (arg : UNSIGNED) return SIGNED; + + -- Returns the maximum (or minimum) of the two numbers provided. + -- All types (both inputs and the output) must be the same. + -- These override the implicit funcitons, using the local ">" operator + function maximum ( + l, r : UNSIGNED) -- inputs + return UNSIGNED; + + function maximum ( + l, r : SIGNED) -- inputs + return SIGNED; + + function minimum ( + l, r : UNSIGNED) -- inputs + return UNSIGNED; + + function minimum ( + l, r : SIGNED) -- inputs + return SIGNED; + + -- Finds the first "Y" in the input string. Returns an integer index + -- into that string. If "Y" does not exist in the string, then the + -- "find_lsb" returns arg'low -1, and "find_msb" returns -1 + function find_lsb ( + arg : UNSIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function find_lsb ( + arg : SIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function find_msb ( + arg : UNSIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function find_msb ( + arg : SIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + -- L.15 + function "and" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.16 + function "and" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.17 + function "or" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.18 + function "or" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.19 + function "nand" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.20 + function "nand" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.21 + function "nor" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.22 + function "nor" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.23 + function "xor" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.24 + function "xor" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.25 + function "xnor" (L : STD_ULOGIC; R : UNSIGNED) return UNSIGNED; + +-- L.26 + function "xnor" (L : UNSIGNED; R : STD_ULOGIC) return UNSIGNED; + +-- L.27 + function "and" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.28 + function "and" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.29 + function "or" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.30 + function "or" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.31 + function "nand" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.32 + function "nand" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.33 + function "nor" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.34 + function "nor" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.35 + function "xor" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.36 + function "xor" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + +-- L.37 + function "xnor" (L : STD_ULOGIC; R : SIGNED) return SIGNED; + +-- L.38 + function "xnor" (L : SIGNED; R : STD_ULOGIC) return SIGNED; + + -- %%% remove 12 functions (old syntax) + function and_reduce(arg : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of and'ing all of the bits of the vector. + + function nand_reduce(arg : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nand'ing all of the bits of the vector. + + function or_reduce(arg : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of or'ing all of the bits of the vector. + + function nor_reduce(arg : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nor'ing all of the bits of the vector. + + function xor_reduce(arg : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xor'ing all of the bits of the vector. + + function xnor_reduce(arg : SIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xnor'ing all of the bits of the vector. + + function and_reduce(arg : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of and'ing all of the bits of the vector. + + function nand_reduce(arg : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nand'ing all of the bits of the vector. + + function or_reduce(arg : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of or'ing all of the bits of the vector. + + function nor_reduce(arg : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of nor'ing all of the bits of the vector. + + function xor_reduce(arg : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xor'ing all of the bits of the vector. + + function xnor_reduce(arg : UNSIGNED) return STD_ULOGIC; + -- Result subtype: STD_LOGIC. + -- Result: Result of xnor'ing all of the bits of the vector. + + -- %%% Uncomment the following 12 functions (new syntax) + -- function "and" ( arg : SIGNED ) RETURN std_ulogic; + -- function "nand" ( arg : SIGNED ) RETURN std_ulogic; + -- function "or" ( arg : SIGNED ) RETURN std_ulogic; + -- function "nor" ( arg : SIGNED ) RETURN std_ulogic; + -- function "xor" ( arg : SIGNED ) RETURN std_ulogic; + -- function "xnor" ( arg : SIGNED ) RETURN std_ulogic; + -- function "and" ( arg : UNSIGNED ) RETURN std_ulogic; + -- function "nand" ( arg : UNSIGNED ) RETURN std_ulogic; + -- function "or" ( arg : UNSIGNED ) RETURN std_ulogic; + -- function "nor" ( arg : UNSIGNED ) RETURN std_ulogic; + -- function "xor" ( arg : UNSIGNED ) RETURN std_ulogic; + -- function "xnor" ( arg : UNSIGNED ) RETURN std_ulogic; + + -- rtl_synthesis off + ------------------------------------------------------------------- + -- string functions + ------------------------------------------------------------------- + function to_string ( + value : in SIGNED; + justified : in SIDE := right; + field : in width := 0 + ) return STRING; + + function to_bstring ( + value : in SIGNED; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + function to_hstring ( + value : in SIGNED; + justified : in SIDE := right; + field : in width := 0 + ) return STRING; + + function to_ostring ( + value : in SIGNED; + justified : in SIDE := right; + field : in width := 0 + ) return STRING; + + function to_string ( + value : in UNSIGNED; + justified : in SIDE := right; + field : in width := 0 + ) return STRING; + + function to_bstring ( + value : in UNSIGNED; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + function to_hstring ( + value : in UNSIGNED; + justified : in SIDE := right; + field : in width := 0 + ) return STRING; + + function to_ostring ( + value : in UNSIGNED; + justified : in SIDE := right; + field : in width := 0 + ) return STRING; + + ----------------------------------------------------------------------------- + -- Read and Write routines + ----------------------------------------------------------------------------- + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in SIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure READ(L : inout LINE; + VALUE : out SIGNED); + + procedure READ(L : inout LINE; + VALUE : out SIGNED; + GOOD : out BOOLEAN); + + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in UNSIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure READ(L : inout LINE; + VALUE : out UNSIGNED); + + procedure READ(L : inout LINE; + VALUE : out UNSIGNED; + GOOD : out BOOLEAN); + +-- alias bread is read [line, SIGNED, BOOLEAN] ; +-- alias bread is read [line, SIGNED] ; +-- alias bwrite is write [line, SIGNED, side, width]; +-- alias bread is read [line, UNSIGNED, BOOLEAN] ; +-- alias bread is read [line, UNSIGNED] ; +-- alias bwrite is write [line, UNSIGNED, side, width]; + + procedure BWRITE ( + L : inout LINE; -- input line + VALUE : in SIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure BREAD(L : inout LINE; + VALUE : out SIGNED); + + procedure BREAD(L : inout LINE; + VALUE : out SIGNED; + GOOD : out BOOLEAN); + + procedure BWRITE ( + L : inout LINE; -- input line + VALUE : in UNSIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure BREAD(L : inout LINE; + VALUE : out UNSIGNED); + + procedure BREAD(L : inout LINE; + VALUE : out UNSIGNED; + GOOD : out BOOLEAN); + + -- Hex and Octal read and write, originally from "std_logic_textio", + -- these procedures have been modified to be more forgiving. + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in SIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure HREAD(L : inout LINE; + VALUE : out SIGNED); + + procedure HREAD(L : inout LINE; + VALUE : out SIGNED; + GOOD : out BOOLEAN); + + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in UNSIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure HREAD(L : inout LINE; + VALUE : out UNSIGNED); + + procedure HREAD(L : inout LINE; + VALUE : out UNSIGNED; + GOOD : out BOOLEAN); + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in SIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OREAD(L : inout LINE; + VALUE : out SIGNED); + + procedure OREAD(L : inout LINE; + VALUE : out SIGNED; + GOOD : out BOOLEAN); + + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in UNSIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OREAD(L : inout LINE; + VALUE : out UNSIGNED); + + procedure OREAD(L : inout LINE; + VALUE : out UNSIGNED; + GOOD : out BOOLEAN); + + -- rtl_synthesis on +end package numeric_std_additions; + +package body numeric_std_additions is + constant NAU : UNSIGNED(0 downto 1) := (others => '0'); + constant NAS : SIGNED(0 downto 1) := (others => '0'); + constant NO_WARNING : BOOLEAN := FALSE; -- default to emit warnings + function MAX (LEFT, RIGHT : INTEGER) return INTEGER is + begin + if LEFT > RIGHT then return LEFT; + else return RIGHT; + end if; + end function MAX; + + -- Id: A.3R + function "+"(L : UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + variable XR : UNSIGNED(L'LENGTH-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L + XR); + end function "+"; + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + variable XL : UNSIGNED(R'LENGTH-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL + R); + end function "+"; + + -- Id: A.4R + function "+"(L : SIGNED; R: STD_ULOGIC) return SIGNED is + variable XR : SIGNED(L'LENGTH-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L + XR); + end function "+"; + + -- Id: A.4L + function "+"(L : STD_ULOGIC; R: SIGNED) return SIGNED is + variable XL : SIGNED(R'LENGTH-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL + R); + end function "+"; + + -- Id: A.9R + function "-"(L : UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + variable XR : UNSIGNED(L'LENGTH-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L - XR); + end function "-"; + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + variable XL : UNSIGNED(R'LENGTH-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL - R); + end function "-"; + + -- Id: A.10R + function "-"(L : SIGNED; R: STD_ULOGIC) return SIGNED is + variable XR : SIGNED(L'LENGTH-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L - XR); + end function "-"; + + -- Id: A.10L + function "-"(L : STD_ULOGIC; R: SIGNED) return SIGNED is + variable XL : SIGNED(R'LENGTH-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL - R); + end function "-"; + + function RESIZE (ARG, SIZE_RES : SIGNED) return SIGNED is + begin + if (SIZE_RES'length = 0) then + return NAS; + else + return resize (ARG, SIZE_RES'length); + end if; + end function RESIZE; + + function RESIZE (ARG, SIZE_RES : UNSIGNED) return UNSIGNED is + begin + if (SIZE_RES'length = 0) then + return NAU; + else + return resize (ARG, SIZE_RES'length); + end if; + end function RESIZE; + + function TO_UNSIGNED (ARG : NATURAL; SIZE_RES : UNSIGNED) return UNSIGNED is + begin + if (SIZE_RES'length = 0) then + return NAU; + else + return TO_UNSIGNED (ARG, SIZE_RES'length); + end if; + end function TO_UNSIGNED; + + function TO_SIGNED (ARG : INTEGER; SIZE_RES : SIGNED) return SIGNED is + begin + if (SIZE_RES'length = 0) then + return NAS; + else + return TO_SIGNED (ARG, SIZE_RES'length); + end if; + end function TO_SIGNED; + + TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; + CONSTANT match_logic_table : stdlogic_table := ( + ----------------------------------------------------- + -- U X 0 1 Z W L H - | | + ----------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | X | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', '1' ), -- | 0 | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', '1' ), -- | 1 | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | Z | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | W | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', '1' ), -- | L | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', '1' ), -- | H | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ) -- | - | + ); + constant no_match_logic_table : stdlogic_table := ( + ----------------------------------------------------- + -- U X 0 1 Z W L H - | | + ----------------------------------------------------- + ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | + ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | + ); + +-- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS + FUNCTION \?=\ ( l, r : std_ulogic ) RETURN std_ulogic IS + VARIABLE value : std_ulogic; + BEGIN + RETURN match_logic_table (l, r); + END FUNCTION \?=\; + function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin + return no_match_logic_table (l, r); + end function \?/=\; + + -- "?=" operator is similar to "std_match", but returns a std_ulogic.. + -- Id: M.2B + function \?=\ (L, R: UNSIGNED) return STD_ULOGIC is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : UNSIGNED(L_LEFT downto 0) is L; + alias XR : UNSIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAX(L'LENGTH, R'LENGTH); + variable LX : UNSIGNED(SIZE-1 downto 0); + variable RX : UNSIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin + -- Logically identical to an "=" operator. + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '1'; + for i in LX'low to LX'high loop + result1 := \?=\(LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + + -- %%% Replace with the following function + -- function "?=" (L, R: UNSIGNED) return std_ulogic is + -- end function "?="; + + -- Id: M.3B + function \?=\ (L, R: SIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : SIGNED(L_LEFT downto 0) is L; + alias XR : SIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAX(L'LENGTH, R'LENGTH); + variable LX : SIGNED(SIZE-1 downto 0); + variable RX : SIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '1'; + for i in LX'low to LX'high loop + result1 := \?=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + -- %%% Replace with the following function +-- function "?=" (L, R: signed) return std_ulogic is +-- end function "?="; + + function \?/=\ (L, R : UNSIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : UNSIGNED(L_LEFT downto 0) is L; + alias XR : UNSIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAX(L'LENGTH, R'LENGTH); + variable LX : UNSIGNED(SIZE-1 downto 0); + variable RX : UNSIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '0'; + for i in LX'low to LX'high loop + result1 := \?/=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; + -- %%% function "?/=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?/="; + function \?/=\ (L, R : SIGNED) return std_ulogic is + constant L_LEFT : INTEGER := L'LENGTH-1; + constant R_LEFT : INTEGER := R'LENGTH-1; + alias XL : SIGNED(L_LEFT downto 0) is L; + alias XR : SIGNED(R_LEFT downto 0) is R; + constant SIZE : NATURAL := MAX(L'LENGTH, R'LENGTH); + variable LX : SIGNED(SIZE-1 downto 0); + variable RX : SIGNED(SIZE-1 downto 0); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + LX := RESIZE(XL, SIZE); + RX := RESIZE(XR, SIZE); + result := '0'; + for i in LX'low to LX'high loop + result1 := \?/=\ (LX(i), RX(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; + -- %%% function "?/=" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?/="; + function \?>\ (L, R : UNSIGNED) return std_ulogic is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% function "?>" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?>"\; + function \?>\ (L, R : SIGNED) return std_ulogic is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "NUMERIC_STD.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% function "?>" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?>"; + function \?>=\ (L, R : UNSIGNED) return std_ulogic is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% function "?>=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?>="; + function \?>=\ (L, R : SIGNED) return std_ulogic is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?>="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "NUMERIC_STD.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% function "?>=" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?>="; + function \?<\ (L, R : UNSIGNED) return std_ulogic is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% function "?<" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?<"; + function \?<\ (L, R : SIGNED) return std_ulogic is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "NUMERIC_STD.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% function "?<" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?<"; + function \?<=\ (L, R : UNSIGNED) return std_ulogic is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% function "?<=" (L, R : UNSIGNED) return std_ulogic is + -- %%% end function "?<="; + function \?<=\ (L, R : SIGNED) return std_ulogic is + begin + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "NUMERIC_STD.""?<="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "NUMERIC_STD.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% function "?<=" (L, R : SIGNED) return std_ulogic is + -- %%% end function "?<="; + + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Procedure takes a carry in into the adder, and provides a carry out. + procedure add_carry ( + L, R : in UNSIGNED; + c_in : in STD_ULOGIC; + result : out UNSIGNED; + c_out : out STD_ULOGIC) is + constant SIZE : NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : UNSIGNED(SIZE downto 0); + variable R01 : UNSIGNED(SIZE downto 0); + variable res_big : UNSIGNED (SIZE downto 0); -- one bit too bit + begin + c_out := 'X'; -- default to X + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + result := NAU; + return; + end if; + L01 := TO_01(RESIZE(L, SIZE+1), 'X'); + R01 := TO_01(RESIZE(R, SIZE+1), 'X'); + if (to_X01(c_in) = 'X') + or (L01(L01'LEFT) = 'X') or (R01(R01'LEFT) = 'X') then + result (SIZE-1 downto 0) := (others => 'X'); + return; + end if; + res_big := L01 + R01 + c_in; + c_out := res_big(SIZE); + result := res_big(SIZE-1 downto 0); + end procedure add_carry; + + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Procedure takes a carry in into the adder, and provides a carry out. + procedure add_carry ( + L, R : in SIGNED; + c_in : in STD_ULOGIC; + result : out SIGNED; + c_out : out STD_ULOGIC) is + constant SIZE : NATURAL := MAX(L'LENGTH, R'LENGTH); + variable L01 : SIGNED(SIZE downto 0); + variable R01 : SIGNED(SIZE downto 0); + variable res_big : SIGNED (SIZE downto 0); + begin + c_out := 'X'; -- default to X + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + result := NAS; + return; + end if; + L01 := TO_01(RESIZE(L, SIZE+1), 'X'); + R01 := TO_01(RESIZE(R, SIZE+1), 'X'); + if (to_X01(c_in) = 'X') + or (L01(L01'LEFT) = 'X') or (R01(R01'LEFT) = 'X') then + result (SIZE-1 downto 0) := (others => 'X'); + return; + end if; + res_big := L01 + R01 + c_in; + c_out := res_big(size) xor res_big(size-1); + result := res_big(size-1 downto 0); + end procedure add_carry; + -- These functions are in std_logic_1164 and are defined for + -- std_logic_vector. They are overloaded here. + FUNCTION To_X01 ( s : UNSIGNED ) RETURN UNSIGNED is + BEGIN + return UNSIGNED (To_X01 (std_logic_vector (s))); + end function To_X01; + + FUNCTION To_X01 ( s : SIGNED ) RETURN SIGNED is + BEGIN + return SIGNED (To_X01 (std_logic_vector (s))); + end function To_X01; + + FUNCTION To_X01Z ( s : UNSIGNED ) RETURN UNSIGNED is + BEGIN + return UNSIGNED (To_X01Z (std_logic_vector (s))); + end function To_X01Z; + + FUNCTION To_X01Z ( s : SIGNED ) RETURN SIGNED is + BEGIN + return SIGNED (To_X01Z (std_logic_vector (s))); + end function To_X01Z; + + FUNCTION To_UX01 ( s : UNSIGNED ) RETURN UNSIGNED is + BEGIN + return UNSIGNED (To_UX01 (std_logic_vector (s))); + end function To_UX01; + + FUNCTION To_UX01 ( s : SIGNED ) RETURN SIGNED is + BEGIN + return SIGNED (To_UX01 (std_logic_vector (s))); + end function To_UX01; + + FUNCTION Is_X ( s : UNSIGNED ) RETURN BOOLEAN is + BEGIN + return Is_X (std_logic_vector (s)); + end function Is_X; + + FUNCTION Is_X ( s : SIGNED ) RETURN BOOLEAN is + BEGIN + return Is_X (std_logic_vector (s)); + end function Is_X; + + -- Arithmetic shifts + -- Functionality NOT the same as the std_logic_vector or bit vector version + function "sla" (ARG : SIGNED; COUNT : INTEGER) RETURN SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end function "sla"; + + -- Functionality NOT the same as the std_logic_vector or bit vector version + function "sla" (ARG : UNSIGNED; COUNT : INTEGER) RETURN UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end function "sla"; + + -- Functionality NOT the same as the std_logic_vector or bit vector version + function "sra" (ARG : SIGNED; COUNT : INTEGER) RETURN SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(ARG, COUNT); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end function "sra"; + + -- Functionality NOT the same as the std_logic_vector or bit vector version + function "sra" (ARG : UNSIGNED; COUNT : INTEGER) RETURN UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(ARG, COUNT); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end function "sra"; + + ----------------------------------------------------------------------------- + -- New/updated functions for VHDL-200X fast track + ----------------------------------------------------------------------------- + -- New conversion functions, these drop or add sign bits only + function remove_sign (arg : SIGNED) return UNSIGNED is + variable result : unsigned (arg'length-1 downto 0); + alias XARG : SIGNED(arg'length-1 downto 0) is ARG; + variable yarg : SIGNED (XARG'range); + begin + if arg'length < 1 then + return NAU; + end if; + if (to_x01(XARG(XARG'high)) = '1') then + yarg := abs (xarg); + else + yarg := to_x01(xarg); + end if; + result := unsigned(yarg); + return result; + end function remove_sign; + + function add_sign (arg : UNSIGNED) return SIGNED is + variable result : signed (arg'length downto 0); + alias XARG : UNSIGNED(arg'length-1 downto 0) is ARG; + begin + if arg'length < 1 then + return NAS; + end if; + result := "0" & SIGNED (to_x01(XARG)); + return result; + end function add_sign; + + -- Returns the maximum (or minimum) of the two numbers provided. + -- All types (both inputs and the output) must be the same. + -- These override the implicit functions, using the local ">" operator + -- UNSIGNED output + function maximum ( + l, r : UNSIGNED) -- inputs + return UNSIGNED is + begin -- function max + if l > r then return l; + else return r; + end if; + end function maximum; + + -- signed output + function maximum ( + l, r : signed) -- inputs + return signed is + begin -- function max + if l > r then return l; + else return r; + end if; + end function maximum; + + -- UNSIGNED output + function minimum ( + l, r : UNSIGNED) -- inputs + return UNSIGNED is + begin -- function minimum + if l < r then return l; + else return r; + end if; + end function minimum; + + -- signed output + function minimum ( + l, r : signed) -- inputs + return signed is + begin -- function minimum + if l < r then return l; + else return r; + end if; + end function minimum; + + function find_lsb ( + arg : UNSIGNED; -- vector argument + y : std_ulogic) -- look for this bit + return integer is + alias xarg : UNSIGNED(arg'length-1 downto 0) is arg; + begin + for_loop: for i in xarg'reverse_range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_lsb; + + function find_lsb ( + arg : signed; -- vector argument + y : std_ulogic) -- look for this bit + return integer is + alias xarg : SIGNED(arg'length-1 downto 0) is arg; + begin + for_loop: for i in xarg'reverse_range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_lsb; + + function find_msb ( + arg : UNSIGNED; -- vector argument + y : std_ulogic) -- look for this bit + return integer is + alias xarg : UNSIGNED(arg'length-1 downto 0) is arg; + begin + for_loop: for i in xarg'range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_msb; + + function find_msb ( + arg : signed; -- vector argument + y : std_ulogic) -- look for this bit + return integer is + alias xarg : SIGNED(arg'length-1 downto 0) is arg; + begin + for_loop: for i in xarg'range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_msb; + + -- Performs the boolean operation on every bit in the vector +-- L.15 + function "and" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + ALIAS rv : UNSIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : UNSIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "and" (l, rv(i)); + END LOOP; + RETURN result; + end function "and"; + +-- L.16 + function "and" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + ALIAS lv : UNSIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : UNSIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "and" (lv(i), r); + END LOOP; + RETURN result; + end function "and"; + +-- L.17 + function "or" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + ALIAS rv : UNSIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : UNSIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "or" (l, rv(i)); + END LOOP; + RETURN result; + end function "or"; + +-- L.18 + function "or" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + ALIAS lv : UNSIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : UNSIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "or" (lv(i), r); + END LOOP; + RETURN result; + end function "or"; + +-- L.19 + function "nand" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + ALIAS rv : UNSIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : UNSIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("and" (l, rv(i))); + END LOOP; + RETURN result; + end function "nand"; + +-- L.20 + function "nand" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + ALIAS lv : UNSIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : UNSIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("and" (lv(i), r)); + END LOOP; + RETURN result; + end function "nand"; + +-- L.21 + function "nor" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + ALIAS rv : UNSIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : UNSIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("or" (l, rv(i))); + END LOOP; + RETURN result; + end function "nor"; + +-- L.22 + function "nor" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + ALIAS lv : UNSIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : UNSIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("or" (lv(i), r)); + END LOOP; + RETURN result; + end function "nor"; + +-- L.23 + function "xor" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + ALIAS rv : UNSIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : UNSIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "xor" (l, rv(i)); + END LOOP; + RETURN result; + end function "xor"; + +-- L.24 + function "xor" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + ALIAS lv : UNSIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : UNSIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "xor" (lv(i), r); + END LOOP; + RETURN result; + end function "xor"; + +-- L.25 + function "xnor" (L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + ALIAS rv : UNSIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : UNSIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("xor" (l, rv(i))); + END LOOP; + RETURN result; + end function "xnor"; + +-- L.26 + function "xnor" (L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + ALIAS lv : UNSIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : UNSIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("xor" (lv(i), r)); + END LOOP; + RETURN result; + end function "xnor"; + +-- L.27 + function "and" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + ALIAS rv : SIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : SIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "and" (l, rv(i)); + END LOOP; + RETURN result; + end function "and"; + +-- L.28 + function "and" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + ALIAS lv : SIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : SIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "and" (lv(i), r); + END LOOP; + RETURN result; + end function "and"; + +-- L.29 + function "or" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + ALIAS rv : SIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : SIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "or" (l, rv(i)); + END LOOP; + RETURN result; + end function "or"; + +-- L.30 + function "or" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + ALIAS lv : SIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : SIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "or" (lv(i), r); + END LOOP; + RETURN result; + end function "or"; + +-- L.31 + function "nand" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + ALIAS rv : SIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : SIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("and" (l, rv(i))); + END LOOP; + RETURN result; + end function "nand"; + +-- L.32 + function "nand" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + ALIAS lv : SIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : SIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("and" (lv(i), r)); + END LOOP; + RETURN result; + end function "nand"; + +-- L.33 + function "nor" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + ALIAS rv : SIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : SIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("or" (l, rv(i))); + END LOOP; + RETURN result; + end function "nor"; + +-- L.34 + function "nor" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + ALIAS lv : SIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : SIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("or" (lv(i), r)); + END LOOP; + RETURN result; + end function "nor"; + +-- L.35 + function "xor" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + ALIAS rv : SIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : SIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "xor" (l, rv(i)); + END LOOP; + RETURN result; + end function "xor"; + +-- L.36 + function "xor" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + ALIAS lv : SIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : SIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "xor" (lv(i), r); + END LOOP; + RETURN result; + end function "xor"; + +-- L.37 + function "xnor" (L: STD_ULOGIC; R: SIGNED) return SIGNED is + ALIAS rv : SIGNED ( 1 TO r'LENGTH ) IS r; + VARIABLE result : SIGNED ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("xor" (l, rv(i))); + END LOOP; + RETURN result; + end function "xnor"; + +-- L.38 + function "xnor" (L: SIGNED; R: STD_ULOGIC) return SIGNED is + ALIAS lv : SIGNED ( 1 TO l'LENGTH ) IS l; + VARIABLE result : SIGNED ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("xor" (lv(i), r)); + END LOOP; + RETURN result; + end function "xnor"; + + -------------------------------------------------------------------------- + -- Reduction operations + -------------------------------------------------------------------------- + -- %%% Remove the following 12 funcitons (old syntax) + function and_reduce (arg : SIGNED ) return std_ulogic is + begin + return and_reduce (UNSIGNED ( arg )); + end function and_reduce; + + FUNCTION and_reduce ( arg : UNSIGNED ) RETURN std_ulogic IS + variable Upper, Lower : std_ulogic; + variable Half : integer; + variable BUS_int : UNSIGNED ( arg'length - 1 downto 0 ); + variable Result : std_ulogic := '1'; -- In the case of a NULL range + BEGIN + if (arg'LENGTH >= 1) then + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "and" (BUS_int(BUS_int'right),BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := and_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := and_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "and" (Upper, Lower); + end if; + end if; + return Result; + END FUNCTION and_reduce; + + function nand_reduce (arg : SIGNED ) return std_ulogic is + begin + return "not" (and_reduce ( arg )); + end function nand_reduce; + + function nand_reduce (arg : UNSIGNED ) return std_ulogic is + begin + return "not" (and_reduce (arg )); + end function nand_reduce; + + function or_reduce (arg : SIGNED ) return std_ulogic is + begin + return or_reduce (UNSIGNED ( arg )); + end function or_reduce; + + function or_reduce (arg : UNSIGNED ) return std_ulogic is + variable Upper, Lower : std_ulogic; + variable Half : integer; + variable BUS_int : UNSIGNED ( arg'length - 1 downto 0 ); + variable Result : std_ulogic := '0'; -- In the case of a NULL range + BEGIN + if (arg'LENGTH >= 1) then + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "or" (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := or_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := or_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "or" (Upper, Lower); + end if; + end if; + return Result; + end function or_reduce; + + function nor_reduce (arg : SIGNED ) return std_ulogic is + begin + RETURN "not"(or_reduce(arg)); + end function nor_reduce; + + function nor_reduce (arg : UNSIGNED ) return std_ulogic is + begin + RETURN "not"(or_reduce(arg)); + end function nor_reduce; + + function xor_reduce (arg : SIGNED ) return std_ulogic is + begin + return xor_reduce (UNSIGNED ( arg )); + end function xor_reduce; + + function xor_reduce (arg : UNSIGNED ) return std_ulogic is + variable Upper, Lower : std_ulogic; + variable Half : integer; + variable BUS_int : UNSIGNED ( arg'length - 1 downto 0 ); + variable Result : std_ulogic := '0'; -- In the case of a NULL range + BEGIN + if (arg'LENGTH >= 1) then + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "xor" (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := xor_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := xor_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "xor" (Upper, Lower); + end if; + end if; + return Result; + end function xor_reduce; + + function xnor_reduce (arg : SIGNED ) return std_ulogic is + begin + RETURN "not"(xor_reduce(arg)); + end function xnor_reduce; + + function xnor_reduce (arg : UNSIGNED ) return std_ulogic is + begin + RETURN "not"(xor_reduce(arg)); + end function xnor_reduce; + + -- %%% Replace the above with the following 12 functions (New syntax) +-- function "and" ( arg : SIGNED ) return std_ulogic is +-- begin +-- return and (std_logic_vector ( arg )); +-- end function "and"; + +-- function "and" ( arg : UNSIGNED ) return std_ulogic is +-- begin +-- return and (std_logic_vector ( arg )); +-- end function "and"; + +-- function "nand" ( arg : SIGNED ) return std_ulogic is +-- begin +-- return nand (std_logic_vector ( arg )); +-- end function "nand"; + +-- function "nand" ( arg : UNSIGNED ) return std_ulogic is +-- begin +-- return nand (std_logic_vector ( arg )); +-- end function "nand"; + +-- function "or" ( arg : SIGNED ) return std_ulogic is +-- begin +-- return or (std_logic_vector ( arg )); +-- end function "or"; + +-- function "or" ( arg : UNSIGNED ) return std_ulogic is +-- begin +-- return or (std_logic_vector ( arg )); +-- end function "or"; + +-- function "nor" ( arg : SIGNED ) return std_ulogic is +-- begin +-- return nor (std_logic_vector ( arg )); +-- end function "nor"; + +-- function "nor" ( arg : UNSIGNED ) return std_ulogic is +-- begin +-- return nor (std_logic_vector ( arg )); +-- end function "nor"; + +-- function "xor" ( arg : SIGNED ) return std_ulogic is +-- begin +-- return xor (std_logic_vector ( arg )); +-- end function "xor"; + +-- function "xor" ( arg : UNSIGNED ) return std_ulogic is +-- begin +-- return xor (std_logic_vector ( arg )); +-- end function "xor"; + +-- function "xnor" ( arg : SIGNED ) return std_ulogic is +-- begin +-- return xnor (std_logic_vector ( arg )); +-- end function "xnor"; + +-- function "xnor" ( arg : UNSIGNED ) return std_ulogic is +-- begin +-- return xnor (std_logic_vector ( arg )); +-- end function "xnor"; + + -- rtl_synthesis off + ------------------------------------------------------------------- + -- TO_STRING + ------------------------------------------------------------------- + -- Type and constant definitions used to map STD_ULOGIC values + -- into/from character values. + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', ERROR); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of character; + type MVL9_indexed_by_char is array (character) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (character) of MVL9plus; + constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9 : MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus : MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => ERROR); + + constant NBSP : character := character'val(160); -- space character + constant NUS : string(2 to 1) := (others => ' '); -- NULL array + + function justify ( + value : STRING; + justified : SIDE := right; + field : width := 0) + return STRING is + constant VAL_LEN : INTEGER := value'length; + variable result : STRING (1 to field) := (others => ' '); + begin -- function justify + -- return value if field is too small + if VAL_LEN >= field then + return value; + end if; + if justified = left then + result(1 to VAL_LEN) := value; + elsif justified = right then + result(field - VAL_LEN + 1 to field) := value; + end if; + return result; + end function justify; + + function to_string ( + value : in signed; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + alias ivalue : signed(1 to value'length) is value; + variable result : string(1 to value'length); + begin + if value'length < 1 then + return NUS; + else + for i in ivalue'range loop + result(i) := MVL9_to_char( iValue(i) ); + end loop; + return justify(result, justified, field); + end if; + end function to_string; + + function to_bstring ( + value : in SIGNED; + justified : in side := RIGHT; + field : in width := 0 + ) return STRING is + begin + return to_string (value, justified, field); + end function to_bstring; + + function to_hstring ( + value : in signed; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + constant ne : integer := (value'length+3)/4; + variable pad : std_logic_vector(0 to (ne*4 - value'length) - 1); + variable ivalue : std_logic_vector(0 to ne*4 - 1); + variable result : string(1 to ne); + variable quad : std_logic_vector(0 to 3); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => value(value'high)); -- Extend sign bit + end if; + ivalue := pad & std_logic_vector (value); + for i in 0 to ne-1 loop + quad := To_X01Z(ivalue(4*i to 4*i+3)); + case quad is + when x"0" => result(i+1) := '0'; + when x"1" => result(i+1) := '1'; + when x"2" => result(i+1) := '2'; + when x"3" => result(i+1) := '3'; + when x"4" => result(i+1) := '4'; + when x"5" => result(i+1) := '5'; + when x"6" => result(i+1) := '6'; + when x"7" => result(i+1) := '7'; + when x"8" => result(i+1) := '8'; + when x"9" => result(i+1) := '9'; + when x"A" => result(i+1) := 'A'; + when x"B" => result(i+1) := 'B'; + when x"C" => result(i+1) := 'C'; + when x"D" => result(i+1) := 'D'; + when x"E" => result(i+1) := 'E'; + when x"F" => result(i+1) := 'F'; + when "ZZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_hstring; + + function to_ostring ( + value : in signed; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + constant ne : integer := (value'length+2)/3; + variable pad : std_logic_vector(0 to (ne*3 - value'length) - 1); + variable ivalue : std_logic_vector(0 to ne*3 - 1); + variable result : string(1 to ne); + variable tri : std_logic_vector(0 to 2); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => value (value'high)); -- Extend sign bit + end if; + ivalue := pad & std_logic_vector (value); + for i in 0 to ne-1 loop + tri := To_X01Z(ivalue(3*i to 3*i+2)); + case tri is + when o"0" => result(i+1) := '0'; + when o"1" => result(i+1) := '1'; + when o"2" => result(i+1) := '2'; + when o"3" => result(i+1) := '3'; + when o"4" => result(i+1) := '4'; + when o"5" => result(i+1) := '5'; + when o"6" => result(i+1) := '6'; + when o"7" => result(i+1) := '7'; + when "ZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_ostring; + + function to_string ( + value : in UNSIGNED; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + begin + return to_string( + value => SIGNED (value), + justified => justified, + field => field); + end function to_string; + + function to_bstring ( + value : in UNSIGNED; + justified : in side := RIGHT; + field : in width := 0 + ) return STRING is + begin + return to_string (value, justified, field); + end function to_bstring; + + function to_hstring ( + value : in UNSIGNED; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + constant ne : integer := (value'length+3)/4; + variable pad : std_logic_vector(0 to (ne*4 - value'length) - 1); + variable ivalue : std_logic_vector(0 to ne*4 - 1); + variable result : string(1 to ne); + variable quad : std_logic_vector(0 to 3); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & std_logic_vector (value); + for i in 0 to ne-1 loop + quad := To_X01Z(ivalue(4*i to 4*i+3)); + case quad is + when x"0" => result(i+1) := '0'; + when x"1" => result(i+1) := '1'; + when x"2" => result(i+1) := '2'; + when x"3" => result(i+1) := '3'; + when x"4" => result(i+1) := '4'; + when x"5" => result(i+1) := '5'; + when x"6" => result(i+1) := '6'; + when x"7" => result(i+1) := '7'; + when x"8" => result(i+1) := '8'; + when x"9" => result(i+1) := '9'; + when x"A" => result(i+1) := 'A'; + when x"B" => result(i+1) := 'B'; + when x"C" => result(i+1) := 'C'; + when x"D" => result(i+1) := 'D'; + when x"E" => result(i+1) := 'E'; + when x"F" => result(i+1) := 'F'; + when "ZZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_hstring; + + function to_ostring ( + value : in UNSIGNED; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + constant ne : integer := (value'length+2)/3; + variable pad : std_logic_vector(0 to (ne*3 - value'length) - 1); + variable ivalue : std_logic_vector(0 to ne*3 - 1); + variable result : string(1 to ne); + variable tri : std_logic_vector(0 to 2); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & std_logic_vector (value); + for i in 0 to ne-1 loop + tri := To_X01Z(ivalue(3*i to 3*i+2)); + case tri is + when o"0" => result(i+1) := '0'; + when o"1" => result(i+1) := '1'; + when o"2" => result(i+1) := '2'; + when o"3" => result(i+1) := '3'; + when o"4" => result(i+1) := '4'; + when o"5" => result(i+1) := '5'; + when o"6" => result(i+1) := '6'; + when o"7" => result(i+1) := '7'; + when "ZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_ostring; + + ----------------------------------------------------------------------------- + -- Read and Write routines + ----------------------------------------------------------------------------- + procedure WRITE ( + L : inout line; -- input line + VALUE : in signed; -- fixed point input + JUSTIFIED : in SIDE := RIGHT; + FIELD : in WIDTH := 0) is + variable s : string(1 to value'length); + variable m : signed(1 to value'length) := value; + begin + for i in 1 to value'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(l, s, justified, field); + end procedure WRITE; + + procedure READ(L : inout LINE; + VALUE : out signed) is + variable m : STD_ULOGIC; + variable c : character; + variable readOk : BOOLEAN; + variable s : string(1 to value'length-1); + variable mv : STD_LOGIC_VECTOR(0 to value'length-1); + begin + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when ((readOk = false) or ((c /= ' ') and (c /= CR) and (c /= HT))); + end loop; + if readOk = false then -- Bail out if there was a bad read + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Error end of string encountered" + severity error; + return; + elsif char_to_MVL9plus(c) = ERROR then + report + "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) Error: Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + end if; + read(l, s, readOk); + if readOk then + for i in 1 to value'length-1 loop + if char_to_MVL9plus(s(i)) = ERROR then + report + "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) Error: Character '" & + s(i) & "' read, expected STD_ULOGIC literal." + severity error; + return; + end if; + end loop; + else + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Error end of string encountered" + severity error; + return; + end if; + mv(0) := char_to_MVL9(c); + for i in 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := signed(mv); + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out signed; + GOOD : out BOOLEAN) is + variable m : STD_ULOGIC; + variable c : character; + variable s : string(1 to value'length-1); + variable mv : STD_LOGIC_VECTOR(0 to value'length-1); + variable readOk : BOOLEAN; + begin + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not readOk then + good := FALSE; + return; + end if; + if char_to_MVL9plus(c) = ERROR then + good := FALSE; + return; + end if; + read(l, s, readOk); + -- Bail out if there was a bad read + if not readOk then + good := FALSE; + return; + end if; + for i in 1 to value'length-1 loop + if char_to_MVL9plus(s(i)) = ERROR then + good := FALSE; + return; + end if; + end loop; + mv(0) := char_to_MVL9(c); + for i in 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := signed(mv); + good := TRUE; + end procedure READ; + + procedure WRITE ( + L : inout line; -- input line + VALUE : in UNSIGNED; -- fixed point input + JUSTIFIED : in SIDE := RIGHT; + FIELD : in WIDTH := 0) is + variable s : string(1 to value'length); + variable m : UNSIGNED(1 to value'length) := value; + begin + for i in 1 to value'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(l, s, justified, field); + end procedure WRITE; + + procedure READ(L : inout LINE; + VALUE : out UNSIGNED) is + variable m : STD_LOGIC; + variable c : character; + variable readOk : BOOLEAN; + variable s : string(1 to value'length-1); + variable mv : STD_LOGIC_VECTOR(0 to value'length-1); + begin + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when ((readOk = false) or ((c /= ' ') and (c /= CR) and (c /= HT))); + end loop; + if readOk = false then -- Bail out if there was a bad read + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Error end of string encountered" + severity error; + return; + elsif char_to_MVL9plus(c) = ERROR then + report + "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) Error: Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + end if; + read(l, s, readOk); + if readOk then + for i in 1 to value'length-1 loop + if char_to_MVL9plus(s(i)) = ERROR then + report + "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) Error: Character '" & + s(i) & "' read, expected STD_ULOGIC literal." + severity error; + return; + end if; + end loop; + else + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Error end of string encountered" + severity error; + return; + end if; + mv(0) := char_to_MVL9(c); + for i in 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := UNSIGNED(mv); + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out UNSIGNED; + GOOD : out BOOLEAN) is + variable m : STD_LOGIC; + variable c : character; + variable s : string(1 to value'length-1); + variable mv : STD_LOGIC_VECTOR(0 to value'length-1); + variable readOk : BOOLEAN; + begin + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not readOk then + good := FALSE; + return; + end if; + if char_to_MVL9plus(c) = ERROR then + good := FALSE; + return; + end if; + read(l, s, readOk); + -- Bail out if there was a bad read + if not readOk then + good := FALSE; + return; + end if; + for i in 1 to value'length-1 loop + if char_to_MVL9plus(s(i)) = ERROR then + good := FALSE; + return; + end if; + end loop; + mv(0) := char_to_MVL9(c); + for i in 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := UNSIGNED(mv); + good := TRUE; + end procedure READ; + + procedure BWRITE ( + L : inout LINE; -- input line + VALUE : in SIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + WRITE (L, VALUE, JUSTIFIED, FIELD); + end procedure BWRITE; + + procedure BREAD(L : inout LINE; + VALUE : out SIGNED) is + begin + READ (L, VALUE); + end procedure BREAD; + + procedure BREAD(L : inout LINE; + VALUE : out SIGNED; + GOOD : out BOOLEAN) is + begin + READ (L, VALUE, GOOD); + end procedure BREAD; + + procedure BWRITE ( + L : inout LINE; -- input line + VALUE : in UNSIGNED; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + WRITE (L, VALUE, JUSTIFIED, FIELD); + end procedure BWRITE; + + procedure BREAD(L : inout LINE; + VALUE : out UNSIGNED) is + begin + READ (L, VALUE); + end procedure BREAD; + + procedure BREAD(L : inout LINE; + VALUE : out UNSIGNED; + GOOD : out BOOLEAN) is + begin + READ (L, VALUE, GOOD); + end procedure BREAD; + -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2QuadBits (C : Character; + RESULT : out std_ulogic_vector(3 downto 0); + GOOD : out Boolean; + ISSUE_ERROR : in Boolean) is + begin + case c is + when '0' => result := x"0"; good := TRUE; + when '1' => result := x"1"; good := TRUE; + when '2' => result := x"2"; good := TRUE; + when '3' => result := x"3"; good := TRUE; + when '4' => result := x"4"; good := TRUE; + when '5' => result := x"5"; good := TRUE; + when '6' => result := x"6"; good := TRUE; + when '7' => result := x"7"; good := TRUE; + when '8' => result := x"8"; good := TRUE; + when '9' => result := x"9"; good := TRUE; + when 'A' | 'a' => result := x"A"; good := TRUE; + when 'B' | 'b' => result := x"B"; good := TRUE; + when 'C' | 'c' => result := x"C"; good := TRUE; + when 'D' | 'd' => result := x"D"; good := TRUE; + when 'E' | 'e' => result := x"E"; good := TRUE; + when 'F' | 'f' => result := x"F"; good := TRUE; + when 'Z' => result := "ZZZZ"; good := TRUE; + when 'X' => result := "XXXX"; good := TRUE; + when others => + assert not ISSUE_ERROR + report + "STD_LOGIC_1164.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + good := FALSE; + end case; + end procedure Char2QuadBits; + + procedure HWRITE ( + L : inout line; -- input line + VALUE : in signed; + JUSTIFIED : in SIDE := RIGHT; + FIELD : in WIDTH := 0) is + begin + WRITE ( L => L, + VALUE => to_hstring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure HWRITE; + + procedure HREAD(L : inout LINE; + VALUE : out signed) is + constant ne : INTEGER := (value'length+3)/4; + constant pad : INTEGER := ne*4 - value'length; + variable ivalue : unsigned(0 to ne*4-1); + begin + HREAD ( L => L, + VALUE => ivalue); -- Read padded string + if (pad > 0) then + if (to_X01(ivalue(0)) = '0') then -- positive + if to_X01(ivalue(0)) = or_reduce(ivalue(0 to pad)) then + VALUE := SIGNED (ivalue (pad to ivalue'high)); + else + assert false + report "NUMERIC_STD.HREAD Error: Signed vector truncated" + severity error; + end if; + else -- negative + if to_X01(ivalue(0)) = and_reduce(ivalue(0 to pad)) then + VALUE := SIGNED (ivalue (pad to ivalue'high)); + else + assert false + report "NUMERIC_STD.HREAD Error: Signed vector truncated" + severity error; + end if; + end if; + else + VALUE := signed (ivalue); + end if; + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out signed; + GOOD : out BOOLEAN) is + constant ne : INTEGER := (value'length+3)/4; + constant pad : INTEGER := ne*4 - value'length; + variable ivalue : UNSIGNED(0 to ne*4-1); + variable ok : BOOLEAN; + begin + HREAD ( L => L, + VALUE => ivalue, -- Read padded STRING + good => ok); + if not ok then + good := FALSE; + return; + end if; + if (pad > 0) then + if (to_X01(ivalue(0)) = '0') then -- positive + if to_X01(ivalue(0)) = or_reduce(ivalue(0 to pad)) then + GOOD := true; + VALUE := SIGNED (ivalue (pad to ivalue'high)); + else + GOOD := false; + end if; + else -- negative + if to_X01(ivalue(0)) = and_reduce(ivalue(0 to pad)) then + GOOD := true; + VALUE := SIGNED (ivalue (pad to ivalue'high)); + else + GOOD := false; + end if; + end if; + else + GOOD := true; + VALUE := signed (ivalue); + end if; + end procedure HREAD; + + procedure HWRITE ( + L : inout line; -- input line + VALUE : in UNSIGNED; + JUSTIFIED : in SIDE := RIGHT; + FIELD : in WIDTH := 0) is + begin + WRITE ( L => L, + VALUE => to_hstring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure HWRITE; + + procedure HREAD(L : inout LINE; + VALUE : out UNSIGNED) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (value'length+3)/4; + constant pad : INTEGER := ne*4 - value'length; + variable sv : std_ulogic_vector(0 to ne*4 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.HREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, TRUE); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "STD_LOGIC_1164.HREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, TRUE); + if not ok then + return; + end if; + end loop; + value := UNSIGNED(to_StdLogicVector(sv (pad to sv'high))); + if or_reduce (UNSIGNED(sv (0 to pad-1))) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.HREAD Error: Vector truncated" + severity error; + end if; + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out UNSIGNED; + GOOD : out BOOLEAN) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (value'length+3)/4; + constant pad : INTEGER := ne*4 - value'length; + variable sv : std_ulogic_vector(0 to ne*4 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + good := FALSE; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + if or_reduce (unsigned(sv (0 to pad-1))) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + value := unsigned(to_stdlogicvector(sv (pad to sv'high))); + good := true; + end if; + end procedure HREAD; + + -- Octal Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2TriBits (C : Character; + RESULT : out std_ulogic_vector(2 downto 0); + GOOD : out Boolean; + ISSUE_ERROR : in Boolean) is + begin + case c is + when '0' => result := o"0"; good := TRUE; + when '1' => result := o"1"; good := TRUE; + when '2' => result := o"2"; good := TRUE; + when '3' => result := o"3"; good := TRUE; + when '4' => result := o"4"; good := TRUE; + when '5' => result := o"5"; good := TRUE; + when '6' => result := o"6"; good := TRUE; + when '7' => result := o"7"; good := TRUE; + when 'Z' => result := "ZZZ"; good := TRUE; + when 'X' => result := "XXX"; good := TRUE; + when others => + assert not ISSUE_ERROR + report + "STD_LOGIC_1164.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + good := FALSE; + end case; + end procedure Char2TriBits; + + procedure OWRITE ( + L : inout line; -- input line + VALUE : in signed; + JUSTIFIED : in SIDE := RIGHT; + FIELD : in WIDTH := 0) is + begin + WRITE ( L => L, + VALUE => to_ostring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure OWRITE; + + procedure OREAD(L : inout LINE; + VALUE : out signed) is + constant ne : INTEGER := (value'length+2)/3; + constant pad : INTEGER := ne*3 - value'length; + variable ivalue : UNSIGNED (0 to ne*3-1); + begin + OREAD ( L => L, + VALUE => ivalue); -- Read padded string + if (pad > 0) then + if (to_X01(ivalue(0)) = '0') then -- positive + if to_X01(ivalue(0)) = or_reduce(ivalue(0 to pad)) then + VALUE := SIGNED (ivalue (pad to ivalue'high)); + else + report "NUMERIC_STD.OREAD Error: Signed vector truncated" + severity error; + end if; + else -- negative + if to_X01(ivalue(0)) = and_reduce(ivalue(0 to pad)) then + VALUE := SIGNED (ivalue (pad to ivalue'high)); + else + report "NUMERIC_STD.OREAD Error: Signed vector truncated" + severity error; + end if; + end if; + else + VALUE := signed (ivalue); + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out signed; + GOOD : out BOOLEAN) is + constant ne : INTEGER := (value'length+2)/3; + constant pad : INTEGER := ne*3 - value'length; + variable ivalue : UNSIGNED (0 to ne*3-1); + variable ok : BOOLEAN; + begin + OREAD ( L => L, + VALUE => ivalue, -- Read padded STRING + good => ok); + -- Bail out if there was a bad read + if not ok then + good := FALSE; + return; + end if; + if (pad > 0) then + if (to_X01(ivalue(0)) = '0') then -- positive + if to_X01(ivalue(0)) = or_reduce(ivalue(0 to pad)) then + VALUE := SIGNED (ivalue (pad to ivalue'high)); + good := true; + else + good := false; + end if; + else -- negative + if to_X01(ivalue(0)) = and_reduce(ivalue(0 to pad)) then + VALUE := SIGNED (ivalue (pad to ivalue'high)); + good := true; + else + good := false; + end if; + end if; + else + good := true; + VALUE := signed (ivalue); + end if; + end procedure OREAD; + + procedure OWRITE ( + L : inout line; -- input line + VALUE : in UNSIGNED; + JUSTIFIED : in SIDE := RIGHT; + FIELD : in WIDTH := 0) is + begin + WRITE ( L => L, + VALUE => to_ostring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure OWRITE; + + procedure OREAD(L : inout LINE; + VALUE : out UNSIGNED) is + variable c : character; + variable ok : boolean; + constant ne : INTEGER := (value'length+2)/3; + constant pad : INTEGER := ne*3 - value'length; + variable sv : std_ulogic_vector(0 to ne*3 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.OREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, TRUE); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "STD_LOGIC_1164.OREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, TRUE); + if not ok then + return; + end if; + end loop; + value := unsigned (to_stdlogicvector (sv (pad to sv'high))); + if or_reduce (unsigned(sv (0 to pad-1))) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.OREAD Error: Vector truncated" + severity error; + end if; + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out UNSIGNED; + GOOD : out BOOLEAN) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (value'length+2)/3; + constant pad : INTEGER := ne*3 - value'length; + variable sv : std_ulogic_vector(0 to ne*3 - 1); + variable s : string(1 to ne-1); + begin + VALUE(VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + good := FALSE; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + value := unsigned (to_stdlogicvector (sv (pad to sv'high))); + if or_reduce (unsigned(sv (0 to pad-1))) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + end if; + end procedure OREAD; + + -- rtl_synthesis on +end package body numeric_std_additions; diff --git a/lib/Standard/ieee/add/numeric_std_unsigned_c.vhdl b/lib/Standard/ieee/add/numeric_std_unsigned_c.vhdl new file mode 100644 index 0000000..f875785 --- /dev/null +++ b/lib/Standard/ieee/add/numeric_std_unsigned_c.vhdl @@ -0,0 +1,1891 @@ +------------------------------------------------------------------------------ +-- "numeric_std_unsigned" package contains functions that treat +-- "std_logic_vector" like an "unsigned" from "numeric_std". +-- There is a dependancey on this package with "numeric_std_additions.vhd". +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee.numeric_std.all; +-- use ieee_proposed.numeric_std_unsigned.all; +-- Last Modified: $Date: 2006-03-14 12:34:06-05 $ +-- RCS ID: $Id: numeric_std_unsigned_c.vhd,v 1.2 2006-03-14 12:34:06-05 l435385 Exp l435385 $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +library IEEE; +use IEEE.STD_LOGIC_1164.all; +package NUMERIC_STD_UNSIGNED is + -- Id: A.3 + function "+" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.3R + function "+"(L : STD_LOGIC_VECTOR; R : STD_ULOGIC) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'RANGE) + -- Result: Similar to A.3 where R is a one bit std_logic_vector + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'RANGE) + -- Result: Similar to A.3 where L is a one bit UNSIGNED + + -- Id: A.5 + function "+" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.9R + function "-"(L : STD_LOGIC_VECTOR; R : STD_ULOGIC) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'RANGE) + -- Result: Similar to A.9 where R is a one bit UNSIGNED + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'RANGE) + -- Result: Similar to A.9 where L is a one bit UNSIGNED + + -- Id: A.11 + function "-" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.17 + function "*" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'LENGTH before multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.23 + function "/" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.29 + function "rem" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.35 + function "mod" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.5 + function ">" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.11 + function "<" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.17 + function "<=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.23 + function ">=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.29 + function "=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.35 + function "/=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: M.2B + -- %%% function "?=" (L, R : STD_LOGIC_VECTOR) return std_ulogic; + -- %%% function "?/=" (L, R : STD_LOGIC_VECTOR) return std_ulogic; + -- %%% function "?>" (L, R : STD_LOGIC_VECTOR) return std_ulogic; + -- %%% function "?>=" (L, R : STD_LOGIC_VECTOR) return std_ulogic; + -- %%% function "?<" (L, R : STD_LOGIC_VECTOR) return std_ulogic; + -- %%% function "?<=" (L, R : STD_LOGIC_VECTOR) return std_ulogic; + function \?=\ (L, R : STD_LOGIC_VECTOR) return std_ulogic; + function \?/=\ (L, R : STD_LOGIC_VECTOR) return std_ulogic; + function \?>\ (L, R : STD_LOGIC_VECTOR) return std_ulogic; + function \?>=\ (L, R : STD_LOGIC_VECTOR) return std_ulogic; + function \?<\ (L, R : STD_LOGIC_VECTOR) return std_ulogic; + function \?<=\ (L, R : STD_LOGIC_VECTOR) return std_ulogic; + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT rightmost elements are lost. + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.2 + function RESIZE (ARG : STD_LOGIC_VECTOR; NEW_SIZE : NATURAL) + return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(NEW_SIZE-1 downto 0) + + -- size_res version, uses the size of the "size_res" input + -- to resize the output + function RESIZE (ARG, SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG : STD_LOGIC_VECTOR) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.3 + function To_StdLogicVector (ARG, SIZE : NATURAL) return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. +-- alias to_slv is +-- To_StdLogicVector [NATURAL, NATURAL return STD_LOGIC_VECTOR]; +-- alias to_std_logic_vector is +-- To_StdLogicVector [NATURAL, NATURAL return STD_LOGIC_VECTOR]; + function to_slv (ARG, SIZE : NATURAL) return STD_LOGIC_VECTOR; + function to_std_logic_vector (ARG, SIZE : NATURAL) return STD_LOGIC_VECTOR; + + -- size_res version, uses size_res to define the size of the output + function To_StdLogicVector (ARG : NATURAL; SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. +-- alias to_slv is +-- To_StdLogicVector [NATURAL, STD_LOGIC_VECTOR return STD_LOGIC_VECTOR]; +-- alias to_std_logic_vector is +-- To_StdLogicVector [NATURAL, STD_LOGIC_VECTOR return STD_LOGIC_VECTOR]; + function to_slv (ARG : NATURAL; SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function to_std_logic_vector (ARG : NATURAL; SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + + --============================================================================ + -- Translation Functions + --============================================================================ + + -- Id: T.1 + function TO_01 (S : STD_LOGIC_VECTOR; XMAP : STD_LOGIC := '0') + return STD_LOGIC_VECTOR; + -- Result subtype: std_logic_vector(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. + + -- add_carry procedures, to provide a carry in and a carry out + procedure add_carry ( + L, R : in STD_LOGIC_VECTOR; + c_in : in STD_ULOGIC; + result : out STD_LOGIC_VECTOR; + c_out : out STD_ULOGIC); + -- Result subtype: STD_LOGIC_VECTOR(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Procedure takes a carry in into the adder, and provides a carry out. + + -- These are here to override the defaults for these functions + function "sra" (ARG : STD_LOGIC_VECTOR; COUNT : INTEGER) + return STD_LOGIC_VECTOR; + function "sla" (ARG : STD_LOGIC_VECTOR; COUNT : INTEGER) + return STD_LOGIC_VECTOR; + + -- Returns the maximum (or minimum) of the two numbers provided. + -- All types (both inputs and the output) must be the same. + function maximum ( + L, R : STD_LOGIC_VECTOR) -- inputs + return STD_LOGIC_VECTOR; + + function minimum ( + L, R : STD_LOGIC_VECTOR) -- inputs + return STD_LOGIC_VECTOR; + + -- Finds the first "Y" in the input string. Returns an integer index + -- into that string. If "Y" does not exist in the string, then the + -- "find_lsb" returns arg'low -1, and "find_msb" returns -1 + function find_lsb ( + arg : STD_LOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function find_msb ( + arg : STD_LOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + -- Repeat the same functions for STD_ULOGIC_VECTOR + -- Id: A.3 + function "+" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.3R + function "+"(L : STD_ULOGIC_VECTOR; R : STD_ULOGIC) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Similar to A.3 where R is a one bit std_logic_vector + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Similar to A.3 where L is a one bit UNSIGNED + + -- Id: A.5 + function "+" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.9R + function "-"(L : STD_ULOGIC_VECTOR; R : STD_ULOGIC) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Similar to A.9 where R is a one bit UNSIGNED + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Similar to A.9 where L is a one bit UNSIGNED + + -- Id: A.11 + function "-" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.17 + function "*" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'LENGTH before multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.23 + function "/" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.29 + function "rem" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.35 + function "mod" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.5 + function ">" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.11 + function "<" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.17 + function "<=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.23 + function ">=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.29 + function "=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.35 + function "/=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: M.2B + -- %%% function "?=" (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + -- %%% function "?/=" (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + -- %%% function "?>" (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + -- %%% function "?>=" (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + -- %%% function "?<" (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + -- %%% function "?<=" (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + function \?=\ (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + function \?/=\ (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + function \?>\ (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + function \?>=\ (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + function \?<\ (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + function \?<=\ (L, R : STD_ULOGIC_VECTOR) return std_ulogic; + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT rightmost elements are lost. + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.2 + function RESIZE (ARG : STD_ULOGIC_VECTOR; NEW_SIZE : NATURAL) + return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(NEW_SIZE-1 downto 0) + + -- size_res version, uses the size of the "size_res" input + -- to resize the output + function RESIZE (ARG, SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG : STD_ULOGIC_VECTOR) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.3 + function To_StdULogicVector (ARG, SIZE : NATURAL) return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. +-- alias to_sulv is +-- To_StdULogicVector [NATURAL, NATURAL return STD_ULOGIC_VECTOR]; +-- alias to_std_ulogic_vector is +-- To_StdULogicVector [NATURAL, NATURAL return STD_ULOGIC_VECTOR]; + function to_sulv (ARG, SIZE : NATURAL) return STD_ULOGIC_VECTOR; + function to_std_ulogic_vector (ARG, SIZE : NATURAL) return STD_ULOGIC_VECTOR; + + -- size_res version, uses size_res to define the size of the output + function To_StdULogicVector (ARG : NATURAL; SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + -- Result subtype: STD_ULOGIC_VECTOR(SIZE_RES'length-1 downto 0) + -- Result: Converts a non-negative INTEGER to an STD_ULOGIC_VECTOR with + -- the same size as SIZE_RES. +-- alias to_sulv is +-- To_StdULogicVector [NATURAL, STD_ULOGIC_VECTOR return STD_ULOGIC_VECTOR]; +-- alias to_std_ulogic_vector is +-- To_StdULogicVector [NATURAL, STD_ULOGIC_VECTOR return STD_ULOGIC_VECTOR]; + function to_sulv (ARG : NATURAL; SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function to_std_ulogic_vector (ARG : NATURAL; SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + + --============================================================================ + -- Translation Functions + --============================================================================ + + -- Id: T.1 + function TO_01 (S : STD_ULOGIC_VECTOR; XMAP : STD_LOGIC := '0') + return STD_ULOGIC_VECTOR; + -- Result subtype: std_logic_vector(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. + + -- add_carry procedures, to provide a carry in and a carry out + procedure add_carry ( + L, R : in STD_ULOGIC_VECTOR; + c_in : in STD_ULOGIC; + result : out STD_ULOGIC_VECTOR; + c_out : out STD_ULOGIC); + -- Result subtype: STD_ULOGIC_VECTOR(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Procedure takes a carry in into the adder, and provides a carry out. + + -- These are here to override the defaults for these functions + function "sra" (ARG : STD_ULOGIC_VECTOR; COUNT : INTEGER) + return STD_ULOGIC_VECTOR; + function "sla" (ARG : STD_ULOGIC_VECTOR; COUNT : INTEGER) + return STD_ULOGIC_VECTOR; + + -- Returns the maximum (or minimum) of the two numbers provided. + -- All types (both inputs and the output) must be the same. + function maximum ( + L, R : STD_ULOGIC_VECTOR) -- inputs + return STD_ULOGIC_VECTOR; + + function minimum ( + L, R : STD_ULOGIC_VECTOR) -- inputs + return STD_ULOGIC_VECTOR; + + -- Finds the first "Y" in the input string. Returns an integer index + -- into that string. If "Y" does not exist in the string, then a + -- -1 is returned. + function find_lsb ( + arg : STD_ULOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; + + function find_msb ( + arg : STD_ULOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER; +end package NUMERIC_STD_UNSIGNED; + +library ieee; +use ieee.numeric_std.all; +use work.numeric_std_additions.all; +package body NUMERIC_STD_UNSIGNED is + + -- Id: A.3 + function "+" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) + UNSIGNED(R)); + end function "+"; + + -- Id: A.5 + function "+" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) + R); + end function "+"; + + -- Id: A.6 + function "+" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L + UNSIGNED(R)); + end function "+"; + + --============================================================================ + + -- Id: A.9 + function "-" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) - UNSIGNED(R)); + end function "-"; + + -- Id: A.11 + function "-" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) - R); + end function "-"; + + -- Id: A.12 + function "-" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L - UNSIGNED(R)); + end function "-"; + + --============================================================================ + + -- Id: A.15 + function "*" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) * UNSIGNED(R)); + end function "*"; + + -- Id: A.17 + function "*" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) * R); + end function "*"; + + -- Id: A.18 + function "*" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L * UNSIGNED(R)); + end function "*"; + + --============================================================================ + + -- Id: A.21 + function "/" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) / UNSIGNED(R)); + end function "/"; + + -- Id: A.23 + function "/" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) / R); + end function "/"; + + -- Id: A.24 + function "/" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L / UNSIGNED(R)); + end function "/"; + + --============================================================================ + + -- Id: A.27 + function "rem" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) rem UNSIGNED(R)); + end function "rem"; + + -- Id: A.29 + function "rem" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) rem R); + end function "rem"; + + -- Id: A.30 + function "rem" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L rem UNSIGNED(R)); + end function "rem"; + + --============================================================================ + + -- Id: A.33 + function "mod" (L, R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) mod UNSIGNED(R)); + end function "mod"; + + -- Id: A.35 + function "mod" (L : STD_LOGIC_VECTOR; R : NATURAL) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (UNSIGNED(L) mod R); + end function "mod"; + + -- Id: A.36 + function "mod" (L : NATURAL; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR (L mod UNSIGNED(R)); + end function "mod"; + + --============================================================================ + + -- Id: C.1 + function ">" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) > UNSIGNED(R); + end function ">"; + + -- Id: C.3 + function ">" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L > UNSIGNED(R); + end function ">"; + + -- Id: C.5 + function ">" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) > R; + end function ">"; + + --============================================================================ + + -- Id: C.7 + function "<" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) < UNSIGNED(R); + end function "<"; + + -- Id: C.9 + function "<" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L < UNSIGNED(R); + end function "<"; + + -- Id: C.11 + function "<" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) < R; + end function "<"; + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) <= UNSIGNED(R); + end function "<="; + + -- Id: C.15 + function "<=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L <= UNSIGNED(R); + end function "<="; + + -- Id: C.17 + function "<=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) <= R; + end function "<="; + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) >= UNSIGNED(R); + end function ">="; + + -- Id: C.21 + function ">=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L >= UNSIGNED(R); + end function ">="; + + -- Id: C.23 + function ">=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) >= R; + end function ">="; + + --============================================================================ + + -- Id: C.25 + function "=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) = UNSIGNED(R); + end function "="; + + -- Id: C.27 + function "=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L = UNSIGNED(R); + end function "="; + + -- Id: C.29 + function "=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) = R; + end function "="; + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) /= UNSIGNED(R); + end function "/="; + + -- Id: C.33 + function "/=" (L : NATURAL; R : STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L /= UNSIGNED(R); + end function "/="; + + -- Id: C.35 + function "/=" (L : STD_LOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return UNSIGNED(L) /= R; + end function "/="; + + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) return STD_LOGIC_VECTOR is + begin + return std_logic_vector (SHIFT_LEFT(unsigned(ARG), COUNT)); + end function SHIFT_LEFT; + + -- Id: S.2 + function SHIFT_RIGHT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) return STD_LOGIC_VECTOR is + begin + return std_logic_vector (SHIFT_RIGHT(unsigned(ARG), COUNT)); + end function SHIFT_RIGHT; + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) return STD_LOGIC_VECTOR is + begin + return std_logic_vector (ROTATE_LEFT(unsigned(ARG), COUNT)); + end function ROTATE_LEFT; + + -- Id: S.6 + function ROTATE_RIGHT (ARG : STD_LOGIC_VECTOR; COUNT : NATURAL) return STD_LOGIC_VECTOR is + begin + return std_logic_vector (ROTATE_RIGHT(unsigned(ARG), COUNT)); + end function ROTATE_RIGHT; + + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG : STD_LOGIC_VECTOR) return NATURAL is + begin + return TO_INTEGER(UNSIGNED(ARG)); + end function TO_INTEGER; + + -- Id: D.3 + function To_StdLogicVector (ARG, SIZE : NATURAL) return STD_LOGIC_VECTOR is + begin + return std_logic_vector (to_unsigned(ARG => ARG, + SIZE => SIZE)); + end function To_StdLogicVector; + + -- size_res version, uses size_res to define the size of the output + function To_StdLogicVector (ARG : NATURAL; SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR is + begin + return std_logic_vector (to_unsigned(ARG => ARG, + SIZE_RES => unsigned(SIZE_RES))); + end function To_StdLogicVector; + + function To_slv (ARG, SIZE : NATURAL) return STD_LOGIC_VECTOR is + begin + return std_logic_vector (to_unsigned(ARG => ARG, + SIZE => SIZE)); + end function To_slv; + + -- size_res version, uses size_res to define the size of the output + function To_slv (ARG : NATURAL; SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR is + begin + return std_logic_vector (to_unsigned(ARG => ARG, + SIZE_RES => unsigned(SIZE_RES))); + end function To_slv; + + function To_Std_Logic_Vector (ARG, SIZE : NATURAL) return STD_LOGIC_VECTOR is + begin + return std_logic_vector (to_unsigned(ARG => ARG, + SIZE => SIZE)); + end function To_Std_Logic_Vector; + + -- size_res version, uses size_res to define the size of the output + function To_Std_Logic_Vector (ARG : NATURAL; SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR is + begin + return std_logic_vector (to_unsigned(ARG => ARG, + SIZE_RES => unsigned(SIZE_RES))); + end function To_Std_Logic_Vector; + + --============================================================================ + + -- function TO_01 is used to convert vectors to the + -- correct form for exported functions, + -- and to report if there is an element which + -- is not in (0, 1, H, L). + + -- Id: T.1 + function TO_01 (S : STD_LOGIC_VECTOR; XMAP : STD_LOGIC := '0') + return STD_LOGIC_VECTOR is + begin + return std_logic_vector ( + to_01 (S => unsigned(S), + XMAP => XMAP)); + end function TO_01; + + -- Id: R.2 + function RESIZE (ARG : STD_LOGIC_VECTOR; NEW_SIZE : NATURAL) + return STD_LOGIC_VECTOR is + begin + return std_logic_vector ( + RESIZE (ARG => unsigned(ARG), + NEW_SIZE => NEW_SIZE)); + end function RESIZE; + + -- size_res version, uses the size of the "size_res" input + -- to resize the output + function RESIZE (ARG, SIZE_RES : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR ( + RESIZE (ARG => unsigned(ARG), + SIZE_RES => unsigned(SIZE_RES))); + end function RESIZE; +--============================================================================== +--============================= New subprograms ================================ +--============================================================================== + + -- Id: A.3R + function "+"(L : STD_LOGIC_VECTOR; R : STD_ULOGIC) return STD_LOGIC_VECTOR is + variable XR : STD_LOGIC_VECTOR(L'length-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L + XR); + end function "+"; + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable XL : STD_LOGIC_VECTOR(R'length-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL + R); + end function "+"; + + -- Id: A.9R + function "-"(L : STD_LOGIC_VECTOR; R : STD_ULOGIC) return STD_LOGIC_VECTOR is + variable XR : STD_LOGIC_VECTOR(L'length-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L - XR); + end function "-"; + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable XL : STD_LOGIC_VECTOR(R'length-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL - R); + end function "-"; + + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Procedure takes a carry in into the adder, and provides a carry out. + procedure add_carry ( + L, R : in STD_LOGIC_VECTOR; + c_in : in STD_ULOGIC; + result : out STD_LOGIC_VECTOR; + c_out : out STD_ULOGIC) is + variable result_i : UNSIGNED (L'length-1 downto 0); + begin + add_carry (L => unsigned(L), + R => unsigned(R), + c_in => c_in, + result => result_i, + c_out => c_out); + result := STD_LOGIC_VECTOR (result_i); + end procedure add_carry; + + -- These are here to override the defaults for these functions + function "sra" (ARG : STD_LOGIC_VECTOR; COUNT : INTEGER) + RETURN STD_LOGIC_VECTOR is + variable result_i : UNSIGNED (ARG'length-1 downto 0); -- unsigned version of arg + begin + result_i := UNSIGNED (arg); + result_i := result_i sra COUNT; + return STD_LOGIC_VECTOR (result_i); + end function "sra"; + + function "sla" (ARG : STD_LOGIC_VECTOR; COUNT : INTEGER) + RETURN STD_LOGIC_VECTOR is + variable result_i : UNSIGNED (ARG'length-1 downto 0); -- unsigned version of arg + begin + result_i := UNSIGNED (arg); + result_i := result_i sla COUNT; + return STD_LOGIC_VECTOR (result_i); + end function "sla"; + + ----------------------------------------------------------------------------- + -- New/updated functions for VHDL-200X fast track + ----------------------------------------------------------------------------- + -- These override the implicit functions. + function maximum ( + L, R : STD_LOGIC_VECTOR) -- inputs + return STD_LOGIC_VECTOR is + begin -- function maximum + if L > R then return L; + else return R; + end if; + end function maximum; + + -- std_logic_vector output + function minimum ( + L, R : STD_LOGIC_VECTOR) -- inputs + return STD_LOGIC_VECTOR is + begin -- function minimum + if L > R then return R; + else return L; + end if; + end function minimum; + + function find_lsb ( + arg : STD_LOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + begin + return find_lsb (arg => unsigned(arg), + y => y); + end function find_lsb; + + function find_msb ( + arg : STD_LOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + begin + return find_msb (arg => unsigned(arg), + y => y); + end function find_msb; + + -- These need to be overloaded because the meaning of the compare operators + -- has changed. + -- %%% Replace with the following (new syntax) + -- %%% function "?=" (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC; + function \?=\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?=\ (UNSIGNED (L), UNSIGNED (R)); + end function \?=\; + -- %%% end function "?="; + + -- %%% function "?/=" (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + function \?/=\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?/=\ (UNSIGNED (L), UNSIGNED (R)); + end function \?/=\; + -- %%% end function "?/="; + + -- %%% function "?>" (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + function \?>\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>\ (UNSIGNED (L), UNSIGNED (R)); + end function \?>\; + -- %%% end function "?>"; + + -- %%% function "?>=" (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + function \?>=\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>=\ (UNSIGNED (L), UNSIGNED (R)); + end function \?>=\; + -- %%% end function "?>="; + + -- %%% function "?<" (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + function \?<\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<\ (UNSIGNED (L), UNSIGNED (R)); + end function \?<\; + -- %%% end function "?<"; + + -- %%% function "?<=" (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + function \?<=\ (L, R : STD_LOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<=\ (UNSIGNED (L), UNSIGNED (R)); + end function \?<=\; + -- %%% end function "?<="; + ---------------------------------------------------------------------------- + -- Std_Ulogic_Vector versions + ---------------------------------------------------------------------------- + -- Conversion functions, these are needed because the base type of "UNSIGNED" + -- is std_logic, not STD_ULOGIC + -- purpose: Converts a std_ulogic_vector to an unsigned + function to_unsigned ( + arg : STD_ULOGIC_VECTOR) + return UNSIGNED is + begin + return UNSIGNED (to_stdlogicvector (arg)); + end function to_unsigned; + + -- purpose: Converts an unsiged to a std_ulogic_vector + function to_sulv ( + arg : UNSIGNED) + return STD_ULOGIC_VECTOR is + begin + return to_stdulogicvector (STD_LOGIC_VECTOR (arg)); + end function to_sulv; + -- + -- Id: A.3 + function "+" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) + to_unsigned(R)); + end function "+"; + + -- Id: A.5 + function "+" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) + R); + end function "+"; + + -- Id: A.6 + function "+" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (L + to_unsigned(R)); + end function "+"; + + --============================================================================ + + -- Id: A.9 + function "-" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) - to_unsigned(R)); + end function "-"; + + -- Id: A.11 + function "-" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) - R); + end function "-"; + + -- Id: A.12 + function "-" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (L - to_unsigned(R)); + end function "-"; + + --============================================================================ + + -- Id: A.15 + function "*" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) * to_unsigned(R)); + end function "*"; + + -- Id: A.17 + function "*" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) * R); + end function "*"; + + -- Id: A.18 + function "*" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (L * to_unsigned(R)); + end function "*"; + + --============================================================================ + + -- Id: A.21 + function "/" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) / to_unsigned(R)); + end function "/"; + + -- Id: A.23 + function "/" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) / R); + end function "/"; + + -- Id: A.24 + function "/" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (L / to_unsigned(R)); + end function "/"; + + --============================================================================ + + -- Id: A.27 + function "rem" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) rem to_unsigned(R)); + end function "rem"; + + -- Id: A.29 + function "rem" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) rem R); + end function "rem"; + + -- Id: A.30 + function "rem" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (L rem to_unsigned(R)); + end function "rem"; + + --============================================================================ + + -- Id: A.33 + function "mod" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) mod to_unsigned(R)); + end function "mod"; + + -- Id: A.35 + function "mod" (L : STD_ULOGIC_VECTOR; R : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(L) mod R); + end function "mod"; + + -- Id: A.36 + function "mod" (L : NATURAL; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + begin + return to_sulv (L mod to_unsigned(R)); + end function "mod"; + + --============================================================================ + + -- Id: C.1 + function ">" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return to_unsigned(L) > to_unsigned(R); + end function ">"; + + -- Id: C.3 + function ">" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L > to_unsigned(R); + end function ">"; + + -- Id: C.5 + function ">" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return to_unsigned(L) > R; + end function ">"; + + --============================================================================ + + -- Id: C.7 + function "<" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return to_unsigned(L) < to_unsigned(R); + end function "<"; + + -- Id: C.9 + function "<" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L < to_unsigned(R); + end function "<"; + + -- Id: C.11 + function "<" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return to_unsigned(L) < R; + end function "<"; + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return to_unsigned(L) <= to_unsigned(R); + end function "<="; + + -- Id: C.15 + function "<=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L <= to_unsigned(R); + end function "<="; + + -- Id: C.17 + function "<=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return to_unsigned(L) <= R; + end function "<="; + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return to_unsigned(L) >= to_unsigned(R); + end function ">="; + + -- Id: C.21 + function ">=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L >= to_unsigned(R); + end function ">="; + + -- Id: C.23 + function ">=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return to_unsigned(L) >= R; + end function ">="; + + --============================================================================ + + -- Id: C.25 + function "=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return to_unsigned(L) = to_unsigned(R); + end function "="; + + -- Id: C.27 + function "=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L = to_unsigned(R); + end function "="; + + -- Id: C.29 + function "=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return to_unsigned(L) = R; + end function "="; + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return to_unsigned(L) /= to_unsigned(R); + end function "/="; + + -- Id: C.33 + function "/=" (L : NATURAL; R : STD_ULOGIC_VECTOR) return BOOLEAN is + begin + return L /= to_unsigned(R); + end function "/="; + + -- Id: C.35 + function "/=" (L : STD_ULOGIC_VECTOR; R : NATURAL) return BOOLEAN is + begin + return to_unsigned(L) /= R; + end function "/="; + + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (SHIFT_LEFT(unsigned(ARG), COUNT)); + end function SHIFT_LEFT; + + -- Id: S.2 + function SHIFT_RIGHT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (SHIFT_RIGHT(unsigned(ARG), COUNT)); + end function SHIFT_RIGHT; + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (ROTATE_LEFT(unsigned(ARG), COUNT)); + end function ROTATE_LEFT; + + -- Id: S.6 + function ROTATE_RIGHT (ARG : STD_ULOGIC_VECTOR; COUNT : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (ROTATE_RIGHT(unsigned(ARG), COUNT)); + end function ROTATE_RIGHT; + + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG : STD_ULOGIC_VECTOR) return NATURAL is + begin + return TO_INTEGER(to_unsigned(ARG)); + end function TO_INTEGER; + + -- Id: D.3 + function To_StdULogicVector (ARG, SIZE : NATURAL) return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(ARG => ARG, + SIZE => SIZE)); + end function To_StdULogicVector; + + -- size_res version, uses size_res to define the size of the output + function To_StdULogicVector (ARG : NATURAL; SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(ARG => ARG, + SIZE_RES => unsigned(SIZE_RES))); + end function To_StdULogicVector; + + function To_sulv (ARG, SIZE : NATURAL) return STD_ULOGIC_VECTOR is + begin + return To_sulv (to_unsigned(ARG => ARG, + SIZE => SIZE)); + end function To_sulv; + + -- size_res version, uses size_res to define the size of the output + function To_sulv (ARG : NATURAL; SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR is + begin + return to_sulv (to_unsigned(ARG => ARG, + SIZE_RES => to_unsigned(SIZE_RES))); + end function To_sulv; + + function To_Std_ULogic_Vector (ARG, SIZE : NATURAL) return STD_ULOGIC_VECTOR is + begin + return To_sulv (to_unsigned(ARG => ARG, + SIZE => SIZE)); + end function To_Std_ULogic_Vector; + + -- size_res version, uses size_res to define the size of the output + function To_Std_ULogic_Vector (ARG : NATURAL; SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR is + begin + return To_sulv (to_unsigned(ARG => ARG, + SIZE_RES => to_unsigned(SIZE_RES))); + end function To_Std_ULogic_Vector; + + --============================================================================ + + -- function TO_01 is used to convert vectors to the + -- correct form for exported functions, + -- and to report if there is an element which + -- is not in (0, 1, H, L). + + -- Id: T.1 + function TO_01 (S : STD_ULOGIC_VECTOR; XMAP : STD_LOGIC := '0') + return STD_ULOGIC_VECTOR is + begin + return to_sulv ( + to_01 (S => unsigned(S), + XMAP => XMAP)); + end function TO_01; + + -- Id: R.2 + function RESIZE (ARG : STD_ULOGIC_VECTOR; NEW_SIZE : NATURAL) + return STD_ULOGIC_VECTOR is + begin + return to_sulv ( + RESIZE (ARG => unsigned(ARG), + NEW_SIZE => NEW_SIZE)); + end function RESIZE; + + -- size_res version, uses the size of the "size_res" input + -- to resize the output + function RESIZE (ARG, SIZE_RES : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR is + begin + return to_sulv ( + RESIZE (ARG => unsigned(ARG), + SIZE_RES => unsigned(SIZE_RES))); + end function RESIZE; +--============================================================================== +--============================= New subprograms ================================ +--============================================================================== + + -- Id: A.3R + function "+"(L : STD_ULOGIC_VECTOR; R : STD_ULOGIC) return STD_ULOGIC_VECTOR is + variable XR : STD_ULOGIC_VECTOR(L'length-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L + XR); + end function "+"; + + -- Id: A.3L + function "+"(L : STD_ULOGIC; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + variable XL : STD_ULOGIC_VECTOR(R'length-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL + R); + end function "+"; + + -- Id: A.9R + function "-"(L : STD_ULOGIC_VECTOR; R : STD_ULOGIC) return STD_ULOGIC_VECTOR is + variable XR : STD_ULOGIC_VECTOR(L'length-1 downto 0) := (others => '0'); + begin + XR(0) := R; + return (L - XR); + end function "-"; + + -- Id: A.9L + function "-"(L : STD_ULOGIC; R : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + variable XL : STD_ULOGIC_VECTOR(R'length-1 downto 0) := (others => '0'); + begin + XL(0) := L; + return (XL - R); + end function "-"; + + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Procedure takes a carry in into the adder, and provides a carry out. + procedure add_carry ( + L, R : in STD_ULOGIC_VECTOR; + c_in : in STD_ULOGIC; + result : out STD_ULOGIC_VECTOR; + c_out : out STD_ULOGIC) is + variable result_i : UNSIGNED (L'length-1 downto 0); + begin + add_carry (L => to_unsigned(L), + R => to_unsigned(R), + c_in => c_in, + result => result_i, + c_out => c_out); + result := to_sulv (result_i); + end procedure add_carry; + + -- These are here to override the defaults for these functions + function "sra" (ARG : STD_ULOGIC_VECTOR; COUNT : INTEGER) + RETURN STD_ULOGIC_VECTOR is + variable result_i : UNSIGNED (ARG'length-1 downto 0); -- unsigned version of arg + begin + result_i := to_unsigned (arg); + result_i := result_i sra COUNT; + return to_sulv (result_i); + end function "sra"; + + function "sla" (ARG : STD_ULOGIC_VECTOR; COUNT : INTEGER) + RETURN STD_ULOGIC_VECTOR is + variable result_i : UNSIGNED (ARG'length-1 downto 0); -- unsigned version of arg + begin + result_i := to_unsigned (arg); + result_i := result_i sla COUNT; + return to_sulv (result_i); + end function "sla"; + + ----------------------------------------------------------------------------- + -- New/updated functions for VHDL-200X fast track + ----------------------------------------------------------------------------- + -- These override the implicit functions. + function maximum ( + L, R : STD_ULOGIC_VECTOR) -- inputs + return STD_ULOGIC_VECTOR is + begin -- function maximum + if L > R then return L; + else return R; + end if; + end function maximum; + + -- std_ulogic_vector output + function minimum ( + L, R : STD_ULOGIC_VECTOR) -- inputs + return STD_ULOGIC_VECTOR is + begin -- function minimum + if L > R then return R; + else return L; + end if; + end function minimum; + + function find_lsb ( + arg : STD_ULOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + begin + return find_lsb (arg => to_unsigned(arg), + y => y); + end function find_lsb; + + function find_msb ( + arg : STD_ULOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + begin + return find_msb (arg => to_unsigned(arg), + y => y); + end function find_msb; + + -- These need to be overloaded because the meaning of the compare operators + -- has changed. + -- %%% Replace with the following (new syntax) + -- %%% function "?=" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC; + function \?=\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?=\ (to_unsigned (L), to_unsigned (R)); + end function \?=\; + -- %%% end function "?="; + + -- %%% function "?/=" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + function \?/=\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?/=\ (to_unsigned (L), to_unsigned (R)); + end function \?/=\; + -- %%% end function "?/="; + + -- %%% function "?>" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + function \?>\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>\ (to_unsigned (L), to_unsigned (R)); + end function \?>\; + -- %%% end function "?>"; + + -- %%% function "?>=" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + function \?>=\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?>=\ (to_unsigned (L), to_unsigned (R)); + end function \?>=\; + -- %%% end function "?>="; + + -- %%% function "?<" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + function \?<\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<\ (to_unsigned (L), to_unsigned (R)); + end function \?<\; + -- %%% end function "?<"; + + -- %%% function "?<=" (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + function \?<=\ (L, R : STD_ULOGIC_VECTOR) return STD_ULOGIC is + begin + return \?<=\ (to_unsigned (L), to_unsigned (R)); + end function \?<=\; + -- %%% end function "?<="; +end package body NUMERIC_STD_UNSIGNED; diff --git a/lib/Standard/ieee/add/standard_additions_c.vhd b/lib/Standard/ieee/add/standard_additions_c.vhd new file mode 100644 index 0000000..4890057 --- /dev/null +++ b/lib/Standard/ieee/add/standard_additions_c.vhd @@ -0,0 +1,1685 @@ +------------------------------------------------------------------------------ +-- "standard_additions" package contains the additions to the built in +-- "standard.std" package. In the final version this package will be implicit. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee_proposed.standard_additions.all; +-- Last Modified: $Date: 2006-03-09 11:19:36-05 $ +-- RCS ID: $Id: standard_additions_c.vhd,v 1.5 2006-03-09 11:19:36-05 l435385 Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +package standard_additions is + -- OS dependant string, New Line + impure function NL return STRING; -- new LINE + + -- This constant gives you your simulator resolution + -- pragma synthesis_off + impure function Sim_Resolution return DELAY_LENGTH; + -- pragma synthesis_on + + -- New type definitions from 1076.1, etc + type REAL_VECTOR is array (NATURAL range <>) of REAL; + type INTEGER_VECTOR is array (NATURAL range <>) of INTEGER; + type TIME_VECTOR is array (NATURAL range <>) of TIME; + type BOOLEAN_VECTOR is array (NATURAL range <>) of BOOLEAN; + + ----------------------------------------------------------------------------- + -- The minimum and maximum functions are implicit functions which are + -- dependant on the ">" implicit function + ----------------------------------------------------------------------------- + function minimum (L, R : BOOLEAN) return BOOLEAN; + function maximum (L, R : BOOLEAN) return BOOLEAN; + function minimum (arg : BOOLEAN_VECTOR) return BOOLEAN; + function maximum (arg : BOOLEAN_VECTOR) return BOOLEAN; + + function minimum (L, R : BIT) return BIT; + function maximum (L, R : BIT) return BIT; + function minimum (arg : BIT_VECTOR) return BIT; + function maximum (arg : BIT_VECTOR) return BIT; + + function minimum (L, R : CHARACTER) return CHARACTER; + function maximum (L, R : CHARACTER) return CHARACTER; + function minimum (arg : STRING) return CHARACTER; + function maximum (arg : STRING) return CHARACTER; + + -- pragma synthesis_off + function minimum (L, R : SEVERITY_LEVEL) return SEVERITY_LEVEL; + function maximum (L, R : SEVERITY_LEVEL) return SEVERITY_LEVEL; + -- pragma synthesis_on + + function minimum (L, R : INTEGER) return INTEGER; + function maximum (L, R : INTEGER) return INTEGER; + function minimum (arg : INTEGER_VECTOR) return INTEGER; + function maximum (arg : INTEGER_VECTOR) return INTEGER; + + function minimum (L, R : REAL) return REAL; + function maximum (L, R : REAL) return REAL; + function minimum (arg : REAL_VECTOR) return REAL; + function maximum (arg : REAL_VECTOR) return REAL; + + function minimum (L, R : TIME) return TIME; + function maximum (L, R : TIME) return TIME; + function minimum (arg : TIME_VECTOR) return TIME; + function maximum (arg : TIME_VECTOR) return TIME; + + function minimum (L, R : STRING) return STRING; + function maximum (L, R : STRING) return STRING; + + function minimum (L, R : BIT_VECTOR) return BIT_VECTOR; + function maximum (L, R : BIT_VECTOR) return BIT_VECTOR; + + -- pragma synthesis_off + function minimum (L, R : FILE_OPEN_KIND) return FILE_OPEN_KIND; + function maximum (L, R : FILE_OPEN_KIND) return FILE_OPEN_KIND; + + function minimum (L, R : FILE_OPEN_STATUS) return FILE_OPEN_STATUS; + function maximum (L, R : FILE_OPEN_STATUS) return FILE_OPEN_STATUS; + -- pragma synthesis_on + + -- THESE SHOULD work, but they don't, so commented out. + -- function minimum (L, R: BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + -- function maximum (L, R: BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + + -- function minimum (L, R : INTEGER_VECTOR) return INTEGER_VECTOR; + -- function maximum (L, R : INTEGER_VECTOR) return INTEGER_VECTOR; + + -- function minimum (L, R: REAL_VECTOR) return REAL_VECTOR; + -- function maximum (L, R: REAL_VECTOR) return REAL_VECTOR; + + -- function minimum (L, R: TIME_VECTOR) return TIME_VECTOR; + -- function maximum (L, R: TIME_VECTOR) return TIME_VECTOR; + + ----------------------------------------------------------------------------- + -- Reduction operations, these perform the boolean operation on all + -- of the bits in a vector. In the case of a NULL array, and returns '1' + -- and or returns '0'. + ----------------------------------------------------------------------------- + -- %%% Replace the following 6 functions with the new syntax + function and_reduce (ARG : BIT_VECTOR) return BIT; + function nand_reduce (ARG : BIT_VECTOR) return BIT; + function or_reduce (ARG : BIT_VECTOR) return BIT; + function nor_reduce (ARG : BIT_VECTOR) return BIT; + function xor_reduce (ARG : BIT_VECTOR) return BIT; + function xnor_reduce (ARG : BIT_VECTOR) return BIT; + function and_reduce (ARG : BOOLEAN_VECTOR) return BOOLEAN; + function nand_reduce (ARG : BOOLEAN_VECTOR) return BOOLEAN; + function or_reduce (ARG : BOOLEAN_VECTOR) return BOOLEAN; + function nor_reduce (ARG : BOOLEAN_VECTOR) return BOOLEAN; + function xor_reduce (ARG : BOOLEAN_VECTOR) return BOOLEAN; + function xnor_reduce (ARG : BOOLEAN_VECTOR) return BOOLEAN; + -- %%% New syntax for reduction operators + -- function "and" (ARG : BIT_VECTOR ) return BIT; + -- function "nand" (ARG : BIT_VECTOR ) return BIT; + -- function "or" (ARG : BIT_VECTOR ) return BIT; + -- function "nor" (ARG : BIT_VECTOR ) return BIT; + -- function "xor" (ARG : BIT_VECTOR ) return BIT; + -- function "xnor" (ARG : BIT_VECTOR ) return BIT; + -- function "and" (ARG : BOOLEAN_VECTOR ) return BOOLEAN; + -- function "nand" (ARG : BOOLEAN_VECTOR ) return BOOLEAN; + -- function "or" (ARG : BOOLEAN_VECTOR ) return BOOLEAN; + -- function "nor" (ARG : BOOLEAN_VECTOR ) return BOOLEAN; + -- function "xor" (ARG : BOOLEAN_VECTOR ) return BOOLEAN; + -- function "xnor" (ARG : BOOLEAN_VECTOR ) return BOOLEAN; + + -- Function to convert a bit to a boolean, replace the following function + function \??\ (arg : BIT) return BOOLEAN; + -- %%% With this operator (new syntax) + -- function "??" (arg : BIT) return BOOLEAN; + function \?=\ (L, R : BIT) return BIT; + function \?/=\ (L, R : BIT) return BIT; + function \?=\ (L, R : BOOLEAN) return BOOLEAN; + function \?/=\ (L, R : BOOLEAN) return BOOLEAN; + function \?=\ (L, R : BIT_VECTOR) return BIT; + function \?/=\ (L, R : BIT_VECTOR) return BIT; + function \?>\ (L, R : BIT_VECTOR) return BIT; + function \?>=\ (L, R : BIT_VECTOR) return BIT; + function \?<\ (L, R : BIT_VECTOR) return BIT; + function \?<=\ (L, R : BIT_VECTOR) return BIT; + -- %%% Replace with the following (new syntax) +-- function "?=" (L, R : BIT) return BIT; +-- function "?/=" (L, R : BIT) return BIT; +-- function "?=" (L, R : BOOLEAN) return BOOLEAN; +-- function "?/=" (L, R : BOOLEAN) return BOOLEAN; +-- function "?=" (L, R : BIT_VECTOR) return BIT; +-- function "?/=" (L, R : BIT_VECTOR) return BIT; +-- function "?>" (L, R : BIT_VECTOR) return BIT; +-- function "?>=" (L, R : BIT_VECTOR) return BIT; +-- function "?<" (L, R : BIT_VECTOR) return BIT; +-- function "?<=" (L, R : BIT_VECTOR) return BIT; + ----------------------------------------------------------------------------- + -- Vector and bit operations, these perform a boolean operation against + -- every bit in a vector. + ----------------------------------------------------------------------------- + function "and" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "and" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "nand" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "nand" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "or" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "or" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "nor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "nor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "xor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "xor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "xnor" (L : BIT_VECTOR; R : BIT) return BIT_VECTOR; + function "xnor" (L : BIT; R : BIT_VECTOR) return BIT_VECTOR; + function "and" (L : BOOLEAN_VECTOR; R : BOOLEAN) return BOOLEAN_VECTOR; + function "and" (L : BOOLEAN; R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "nand" (L : BOOLEAN_VECTOR; R : BOOLEAN) return BOOLEAN_VECTOR; + function "nand" (L : BOOLEAN; R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "or" (L : BOOLEAN_VECTOR; R : BOOLEAN) return BOOLEAN_VECTOR; + function "or" (L : BOOLEAN; R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "nor" (L : BOOLEAN_VECTOR; R : BOOLEAN) return BOOLEAN_VECTOR; + function "nor" (L : BOOLEAN; R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "xor" (L : BOOLEAN_VECTOR; R : BOOLEAN) return BOOLEAN_VECTOR; + function "xor" (L : BOOLEAN; R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "xnor" (L : BOOLEAN_VECTOR; R : BOOLEAN) return BOOLEAN_VECTOR; + function "xnor" (L : BOOLEAN; R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + + -- BOOLEAN_VECTOR functions + function "not" (L : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "and" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "nand" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "or" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "nor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "xor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + function "xnor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR; + ----------------------------------------------------------------------------- + -- boolean and bit operations, returning type "BIT". + ----------------------------------------------------------------------------- + function "and" (L : BIT; R : BOOLEAN) return BIT; + function "and" (L : BOOLEAN; R : BIT) return BIT; + function "or" (L : BIT; R : BOOLEAN) return BIT; + function "or" (L : BOOLEAN; R : BIT) return BIT; + function "xor" (L : BIT; R : BOOLEAN) return BIT; + function "xor" (L : BOOLEAN; R : BIT) return BIT; + function "nand" (L : BIT; R : BOOLEAN) return BIT; + function "nand" (L : BOOLEAN; R : BIT) return BIT; + function "nor" (L : BIT; R : BOOLEAN) return BIT; + function "nor" (L : BOOLEAN; R : BIT) return BIT; + function "xnor" (L : BIT; R : BOOLEAN) return BIT; + function "xnor" (L : BOOLEAN; R : BIT) return BIT; + + ------------------------------------------------------------------- + -- edge detection + ------------------------------------------------------------------- + function rising_edge (signal s : BIT) return BOOLEAN; + function falling_edge (signal s : BIT) return BOOLEAN; + +end package standard_additions; + +package body standard_additions is + -- OS dependent constant to be LF on a UNIX machine + -- purpose: returns the new line constant + impure function NL + return STRING is + constant UNIX_NEWLINE : STRING := (1 => LF); + constant PC_NEWLINE : STRING := (1 => CR, 2 => LF); + begin + return UNIX_NEWLINE; + -- If on a PC, return PC_NEWLINE + end function NL; + + -- pragma synthesis_off + constant BASE_TIME_ARRAY : time_vector := + ( + 1 fs, 10 fs, 100 fs, + 1 ps, 10 ps, 100 ps, + 1 ns, 10 ns, 100 ns, + 1 us, 10 us, 100 us, + 1 ms, 10 ms, 100 ms, + 1 sec, 10 sec, 100 sec, + 1 min, 10 min, 100 min, + 1 hr, 10 hr, 100 hr + ) ; + + impure function Sim_Resolution + return DELAY_LENGTH is + begin + for i in BASE_TIME_ARRAY'range loop + if BASE_TIME_ARRAY(i) > 0 hr then + return BASE_TIME_ARRAY(i); + end if; + end loop; + report "STANDATD.SIM_RESOLUTION: Simulator resolution not less than 100 hr" + severity failure; + return 1 ns; + end function Sim_Resolution; + -- pragma synthesis_on + + --%%% Examples of how the maximum and minimum funcitons work. REMOVE + function minimum (L, R : BOOLEAN) return BOOLEAN is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : BOOLEAN) return BOOLEAN is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + function minimum (L, R : BIT) return BIT is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : BIT) return BIT is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + function maximum (L, R : INTEGER) return INTEGER is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + function minimum (L, R : INTEGER) return INTEGER is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + + function maximum (L, R : BIT_VECTOR) return BIT_VECTOR is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + function minimum (L, R : BIT_VECTOR) return BIT_VECTOR is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + + function minimum (L, R : CHARACTER) return CHARACTER is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : CHARACTER) return CHARACTER is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + -- pragma synthesis_off + function minimum (L, R : SEVERITY_LEVEL) return SEVERITY_LEVEL is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : SEVERITY_LEVEL) return SEVERITY_LEVEL is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + -- pragma synthesis_on + + function minimum (L, R : STRING) return STRING is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : STRING) return STRING is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + function minimum (L, R : REAL) return REAL is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : REAL) return REAL is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + function minimum (L, R : TIME) return TIME is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : TIME) return TIME is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + -- pragma synthesis_off + function minimum (L, R : FILE_OPEN_KIND) return FILE_OPEN_KIND is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : FILE_OPEN_KIND) return FILE_OPEN_KIND is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + + function minimum (L, R : FILE_OPEN_STATUS) return FILE_OPEN_STATUS is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : FILE_OPEN_STATUS) return FILE_OPEN_STATUS is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + -- pragma synthesis_on + + -- THESE SHOULD work, but they don't, so commented out. +-- function minimum (L, R: REAL_VECTOR) return REAL_VECTOR is +-- begin +-- if L > R then return R; +-- else return L; +-- end if; +-- end function minimum; +-- function maximum (L, R: REAL_VECTOR) return REAL_VECTOR is +-- begin +-- if L > R then return L; +-- else return R; +-- end if; +-- end function maximum; +-- function minimum (L, R: INTEGER_VECTOR) return INTEGER_VECTOR is +-- begin +-- if L > R then return R; +-- else return L; +-- end if; +-- end function minimum; +-- function maximum (L, R: INTEGER_VECTOR) return INTEGER_VECTOR is +-- begin +-- if L > R then return L; +-- else return R; +-- end if; +-- end function maximum; +-- function minimum (L, R: TIME_VECTOR) return TIME_VECTOR is +-- begin +-- if L > R then return R; +-- else return L; +-- end if; +-- end function minimum; +-- function maximum (L, R: TIME_VECTOR) return TIME_VECTOR is +-- begin +-- if L > R then return L; +-- else return R; +-- end if; +-- end function maximum; +-- function minimum (L, R: BOOLEAN_VECTOR) return BOOLEAN_VECTOR is +-- begin +-- if L > R then return R; +-- else return L; +-- end if; +-- end function minimum; +-- function maximum (L, R: BOOLEAN_VECTOR) return BOOLEAN_VECTOR is +-- begin +-- if L > R then return L; +-- else return R; +-- end if; +-- end function maximum; + + function minimum (arg : BOOLEAN_VECTOR) return BOOLEAN is + variable Upper, Lower : BOOLEAN; + variable Half : INTEGER; + alias BUS_int : boolean_vector (arg'length - 1 downto 0) is arg; + variable Result : BOOLEAN := BOOLEAN'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := minimum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := minimum (BUS_int (BUS_int'left downto Half)); + Lower := minimum (BUS_int (Half - 1 downto BUS_int'right)); + Result := minimum (Upper, Lower); + end if; + end if; + return Result; + end function minimum; + + function maximum (arg : BOOLEAN_VECTOR) return BOOLEAN is + variable Upper, Lower : BOOLEAN; + variable Half : INTEGER; + alias BUS_int : boolean_vector (arg'length - 1 downto 0) is arg; + variable Result : BOOLEAN := BOOLEAN'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := maximum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := maximum (BUS_int (BUS_int'left downto Half)); + Lower := maximum (BUS_int (Half - 1 downto BUS_int'right)); + Result := maximum (Upper, Lower); + end if; + end if; + return Result; + end function maximum; + + function minimum (arg : BIT_VECTOR) return BIT is + variable Upper, Lower : BIT; + variable Half : INTEGER; + alias BUS_int : BIT_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : BIT := BIT'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := minimum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := minimum (BUS_int (BUS_int'left downto Half)); + Lower := minimum (BUS_int (Half - 1 downto BUS_int'right)); + Result := minimum (Upper, Lower); + end if; + end if; + return Result; + end function minimum; + + function maximum (arg : BIT_VECTOR) return BIT is + variable Upper, Lower : BIT; + variable Half : INTEGER; + alias BUS_int : BIT_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : BIT := BIT'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := maximum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := maximum (BUS_int (BUS_int'left downto Half)); + Lower := maximum (BUS_int (Half - 1 downto BUS_int'right)); + Result := maximum (Upper, Lower); + end if; + end if; + return Result; + end function maximum; + + function minimum (arg : STRING) return CHARACTER is + variable Upper, Lower : CHARACTER; + variable Half : INTEGER; + alias BUS_int : STRING (arg'length downto 1) is arg; + variable Result : CHARACTER := CHARACTER'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := minimum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := minimum (BUS_int (BUS_int'left downto Half)); + Lower := minimum (BUS_int (Half - 1 downto BUS_int'right)); + Result := minimum (Upper, Lower); + end if; + end if; + return Result; + end function minimum; + + function maximum (arg : STRING) return CHARACTER is + variable Upper, Lower : CHARACTER; + variable Half : INTEGER; + alias BUS_int : STRING (arg'length downto 1) is arg; + variable Result : CHARACTER := CHARACTER'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := maximum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := maximum (BUS_int (BUS_int'left downto Half)); + Lower := maximum (BUS_int (Half - 1 downto BUS_int'right)); + Result := maximum (Upper, Lower); + end if; + end if; + return Result; + end function maximum; + + function minimum (arg : INTEGER_VECTOR) return INTEGER is + variable Upper, Lower : INTEGER; + variable Half : INTEGER; + alias BUS_int : INTEGER_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : INTEGER := INTEGER'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := minimum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := minimum (BUS_int (BUS_int'left downto Half)); + Lower := minimum (BUS_int (Half - 1 downto BUS_int'right)); + Result := minimum (Upper, Lower); + end if; + end if; + return Result; + end function minimum; + + function maximum (arg : INTEGER_VECTOR) return INTEGER is + variable Upper, Lower : INTEGER; + variable Half : INTEGER; + alias BUS_int : INTEGER_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : INTEGER := INTEGER'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := maximum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := maximum (BUS_int (BUS_int'left downto Half)); + Lower := maximum (BUS_int (Half - 1 downto BUS_int'right)); + Result := maximum (Upper, Lower); + end if; + end if; + return Result; + end function maximum; + + function minimum (arg : REAL_VECTOR) return REAL is + variable Upper, Lower : REAL; + variable Half : INTEGER; + alias BUS_int : REAL_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : REAL := REAL'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := minimum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := minimum (BUS_int (BUS_int'left downto Half)); + Lower := minimum (BUS_int (Half - 1 downto BUS_int'right)); + Result := minimum (Upper, Lower); + end if; + end if; + return Result; + end function minimum; + + function maximum (arg : REAL_VECTOR) return REAL is + variable Upper, Lower : REAL; + variable Half : INTEGER; + alias BUS_int : REAL_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : REAL := REAL'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := maximum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := maximum (BUS_int (BUS_int'left downto Half)); + Lower := maximum (BUS_int (Half - 1 downto BUS_int'right)); + Result := maximum (Upper, Lower); + end if; + end if; + return Result; + end function maximum; + + function minimum (arg : TIME_VECTOR) return TIME is + variable Upper, Lower : TIME; + variable Half : INTEGER; + alias BUS_int : TIME_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : TIME := TIME'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := minimum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := minimum (BUS_int (BUS_int'left downto Half)); + Lower := minimum (BUS_int (Half - 1 downto BUS_int'right)); + Result := minimum (Upper, Lower); + end if; + end if; + return Result; + end function minimum; + + function maximum (arg : TIME_VECTOR) return TIME is + variable Upper, Lower : TIME; + variable Half : INTEGER; + alias BUS_int : TIME_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : TIME := TIME'low; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := maximum (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := maximum (BUS_int (BUS_int'left downto Half)); + Lower := maximum (BUS_int (Half - 1 downto BUS_int'right)); + Result := maximum (Upper, Lower); + end if; + end if; + return Result; + end function maximum; + ---------------------------------------------------------------------------- + -- Boolean_Vector array logical functions + ---------------------------------------------------------------------------- + function "not" (l : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := not lv(i); + end loop; + return result; + end function "not"; + function "and" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "standard.""and"" arguments are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := lv(i) and rv(i); + end loop; + end if; + return result; + end function "and"; + function "nand" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "standard.""nand"" arguments are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := lv(i) nand rv(i); + end loop; + end if; + return result; + end function "nand"; + function "or" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "standard.""or"" arguments are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := lv(i) or rv(i); + end loop; + end if; + return result; + end function "or"; + function "nor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "standard.""nor"" arguments are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := lv(i) nor rv(i); + end loop; + end if; + return result; + end function "nor"; + function "xor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "standard.""xor"" arguments are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := lv(i) xor rv(i); + end loop; + end if; + return result; + end function "xor"; + function "xnor" (L, R : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + if (l'length /= r'length) then + assert false + report "standard.""xnor"" arguments are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := lv(i) xnor rv(i); + end loop; + end if; + return result; + end function "xnor"; + + --%%% Uncomment the following functions (new syntax) +-- ------------------------------------------------------------------- +-- -- and +-- ------------------------------------------------------------------- +-- function "and" (arg : BIT_VECTOR) return BIT is +-- variable Upper, Lower : bit; +-- variable Half : integer; +-- alias BUS_int : bit_vector ( arg'length - 1 downto 0 ) is arg; +-- variable Result : bit := '1'; -- In the case of a NULL range +-- begin +-- if (arg'LENGTH >= 1) then +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := BUS_int(BUS_int'right) and BUS_int(BUS_int'left); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := and ( BUS_int ( BUS_int'left downto Half )); +-- Lower := and ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := Upper and Lower; +-- end if; +-- end if; +-- return Result; +-- end function "and"; + +-- ------------------------------------------------------------------- +-- -- nand +-- ------------------------------------------------------------------- +-- function "nand" (arg : BIT_VECTOR) return BIT is +-- begin +-- return not and arg; +-- end function "nand"; + +-- ------------------------------------------------------------------- +-- -- or +-- ------------------------------------------------------------------- +-- function "or" (arg : BIT_VECTOR) return BIT is +-- variable Upper, Lower : bit; +-- variable Half : integer; +-- alias BUS_int : bit_vector ( arg'length - 1 downto 0 ) is arg; +-- variable Result : bit := '0'; -- In the case of a NULL range +-- begin +-- if (arg'LENGTH >= 1) then +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := BUS_int(BUS_int'right) or BUS_int(BUS_int'left); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := or ( BUS_int ( BUS_int'left downto Half )); +-- Lower := or ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := Upper or Lower; +-- end if; +-- end if; +-- return Result; +-- end function "or"; + +-- ------------------------------------------------------------------- +-- -- nor +-- ------------------------------------------------------------------- +-- function nor (arg : BIT_VECTOR) return BIT is +-- begin +-- return not or arg; +-- end function nor; + +-- ------------------------------------------------------------------- +-- -- xor +-- ------------------------------------------------------------------- +-- function "xor" (arg : BIT_VECTOR) return BIT is +-- variable Upper, Lower : bit; +-- variable Half : integer; +-- alias BUS_int : bit_vector ( arg'length - 1 downto 0 ) is arg; +-- variable Result : bit := '0'; -- In the case of a NULL range +-- begin +-- if (arg'LENGTH >= 1) then +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := xor ( BUS_int ( BUS_int'left downto Half )); +-- Lower := xor ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := Upper xor Lower; +-- end if; +-- end if; +-- return Result; +-- end function "xor"; +-- +-- ------------------------------------------------------------------- +-- -- xnor +-- ------------------------------------------------------------------- +-- function "xnor" (arg : BIT_VECTOR) return BIT is +-- begin +-- return not xor arg; +-- end function "xnor"; +-- +-- -- BOOLEAN_VECTOR routines +-- ------------------------------------------------------------------- +-- -- and +-- ------------------------------------------------------------------- +-- function "and" (arg : BOOLEAN_VECTOR) return BOOLEAN is +-- variable Upper, Lower : bit; +-- variable Half : integer; +-- alias BUS_int : bit_vector ( arg'length - 1 downto 0 ) is arg; +-- variable Result : bit := '1'; -- In the case of a NULL range +-- begin +-- if (arg'LENGTH >= 1) then +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := BUS_int(BUS_int'right) and BUS_int(BUS_int'left); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := and ( BUS_int ( BUS_int'left downto Half )); +-- Lower := and ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := Upper and Lower; +-- end if; +-- end if; +-- return Result; +-- end function "and"; + +-- ------------------------------------------------------------------- +-- -- nand +-- ------------------------------------------------------------------- +-- function "nand" (arg : BOOLEAN_VECTOR) return BOOLEAN is +-- begin +-- return not and arg; +-- end function "nand"; + +-- ------------------------------------------------------------------- +-- -- or +-- ------------------------------------------------------------------- +-- function "or" (arg : BOOLEAN_VECTOR) return BOOLEAN is +-- variable Upper, Lower : bit; +-- variable Half : integer; +-- alias BUS_int : bit_vector ( arg'length - 1 downto 0 ) is arg; +-- variable Result : bit := '0'; -- In the case of a NULL range +-- begin +-- if (arg'LENGTH >= 1) then +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := BUS_int(BUS_int'right) or BUS_int(BUS_int'left); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := or ( BUS_int ( BUS_int'left downto Half )); +-- Lower := or ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := Upper or Lower; +-- end if; +-- end if; +-- return Result; +-- end function "or"; + +-- ------------------------------------------------------------------- +-- -- nor +-- ------------------------------------------------------------------- +-- function nor (arg : BOOLEAN_VECTOR) return BOOLEAN is +-- begin +-- return not or arg; +-- end function nor; + +-- ------------------------------------------------------------------- +-- -- xor +-- ------------------------------------------------------------------- +-- function "xor" (arg : BOOLEAN_VECTOR) return BOOLEAN is +-- variable Upper, Lower : bit; +-- variable Half : integer; +-- alias BUS_int : bit_vector ( arg'length - 1 downto 0 ) is arg; +-- variable Result : bit := '0'; -- In the case of a NULL range +-- begin +-- if (arg'LENGTH >= 1) then +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := xor ( BUS_int ( BUS_int'left downto Half )); +-- Lower := xor ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := Upper xor Lower; +-- end if; +-- end if; +-- return Result; +-- end function "xor"; + +-- ------------------------------------------------------------------- +-- -- xnor +-- ------------------------------------------------------------------- +-- function "xnor" (arg : BOOLEAN_VECTOR) return BOOLEAN is +-- begin +-- return not xor arg; +-- end function "xnor"; +--%%% end uncomment + --%%% REMOVE the following functions (old syntax) + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + function and_reduce (arg : BIT_VECTOR) return BIT is + variable Upper, Lower : BIT; + variable Half : INTEGER; + alias BUS_int : BIT_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : BIT := '1'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) and BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := and_reduce (BUS_int (BUS_int'left downto Half)); + Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper and Lower; + end if; + end if; + return Result; + end function and_reduce; + + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + function nand_reduce (arg : BIT_VECTOR) return BIT is + begin + return not and_reduce(arg); + end function nand_reduce; + + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + function or_reduce (arg : BIT_VECTOR) return BIT is + variable Upper, Lower : BIT; + variable Half : INTEGER; + alias BUS_int : BIT_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : BIT := '0'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) or BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := or_reduce (BUS_int (BUS_int'left downto Half)); + Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper or Lower; + end if; + end if; + return Result; + end function or_reduce; + + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + function nor_reduce (arg : BIT_VECTOR) return BIT is + begin + return not or_reduce(arg); + end function nor_reduce; + + ------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + function xor_reduce (arg : BIT_VECTOR) return BIT is + variable Upper, Lower : BIT; + variable Half : INTEGER; + alias BUS_int : BIT_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : BIT := '0'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := xor_reduce (BUS_int (BUS_int'left downto Half)); + Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper xor Lower; + end if; + end if; + return Result; + end function xor_reduce; + + ------------------------------------------------------------------- + -- xnor + ------------------------------------------------------------------- + function xnor_reduce (arg : BIT_VECTOR) return BIT is + begin + return not xor_reduce(arg); + end function xnor_reduce; + + -- BOOLEAN_VECTOR routines + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + function and_reduce (arg : BOOLEAN_VECTOR) return BOOLEAN is + variable Upper, Lower : BOOLEAN; + variable Half : INTEGER; + alias BUS_int : BOOLEAN_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : BOOLEAN := true; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) and BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := and_reduce (BUS_int (BUS_int'left downto Half)); + Lower := and_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper and Lower; + end if; + end if; + return Result; + end function and_reduce; + + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + function nand_reduce (arg : BOOLEAN_VECTOR) return BOOLEAN is + begin + return not and_reduce(arg); + end function nand_reduce; + + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + function or_reduce (arg : BOOLEAN_VECTOR) return BOOLEAN is + variable Upper, Lower : BOOLEAN; + variable Half : INTEGER; + alias BUS_int : BOOLEAN_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : BOOLEAN := false; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) or BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := or_reduce (BUS_int (BUS_int'left downto Half)); + Lower := or_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper or Lower; + end if; + end if; + return Result; + end function or_reduce; + + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + function nor_reduce (arg : BOOLEAN_VECTOR) return BOOLEAN is + begin + return not or_reduce(arg); + end function nor_reduce; + + ------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + function xor_reduce (arg : BOOLEAN_VECTOR) return BOOLEAN is + variable Upper, Lower : BOOLEAN; + variable Half : INTEGER; + alias BUS_int : BOOLEAN_VECTOR (arg'length - 1 downto 0) is arg; + variable Result : BOOLEAN := false; -- In the case of a NULL range + begin + if (arg'length >= 1) then + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := xor_reduce (BUS_int (BUS_int'left downto Half)); + Lower := xor_reduce (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper xor Lower; + end if; + end if; + return Result; + end function xor_reduce; + + ------------------------------------------------------------------- + -- xnor + ------------------------------------------------------------------- + function xnor_reduce (arg : BOOLEAN_VECTOR) return BOOLEAN is + begin + return not xor_reduce(arg); + end function xnor_reduce; +--%%% end remove + + -- purpose: Converts a bit to a boolean + -- %%% function "??" (arg : BIT) return BOOLEAN is + function \??\ (arg : BIT) return BOOLEAN is + begin + return arg = '1'; + end function \??\; + -- %%% end function "??"; + + -- Implicit funcitons + -- %%% function "?=" (L, R : BIT) return BIT is + function \?=\ (L, R : BIT) return BIT is + begin + if L = R then + return '1'; + else + return '0'; + end if; + end function \?=\; + -- %%% end function "?="; + -- %%% function "?/=" (L, R : BIT) return BIT is + function \?/=\ (L, R : BIT) return BIT is + begin + if L /= R then + return '1'; + else + return '0'; + end if; + end function \?/=\; + -- %%% end function "?/="; + -- %%% function "?=" (L, R : BOOLEAN) return BOOLEAN is + function \?=\ (L, R : BOOLEAN) return BOOLEAN is + begin + return L = R; + end function \?=\; + -- %%% end function "?="; + -- %%% function "?/=" (L, R : BOOLEAN) return BOOLEAN is + function \?/=\ (L, R : BOOLEAN) return BOOLEAN is + begin + return L /= R; + end function \?/=\; + -- %%% end function "?/="; + -- %%% function "?=" (L, R : BIT_VECTOR) return BIT is + function \?=\ (L, R : BIT_VECTOR) return BIT is + begin + if L = R then + return '1'; + else + return '0'; + end if; + end function \?=\; + -- %%% end function "?="; + -- %%% function "?/=" (L, R : BIT_VECTOR) return BIT is + function \?/=\ (L, R : BIT_VECTOR) return BIT is + begin + if L /= R then + return '1'; + else + return '0'; + end if; + end function \?/=\; + -- %%% end function "?/="; + -- %%% function "?>" (L, R : BIT_VECTOR) return BIT is + function \?>\ (L, R : BIT_VECTOR) return BIT is + begin + if L > R then + return '1'; + else + return '0'; + end if; + end function \?>\; + -- %%% end function "?>"; + -- %%% function "?>=" (L, R : BIT_VECTOR) return BIT is + function \?>=\ (L, R : BIT_VECTOR) return BIT is + begin + if L >= R then + return '1'; + else + return '0'; + end if; + end function \?>=\; + -- %%% end function "?>="; + -- %%% function "?<" (L, R : BIT_VECTOR) return BIT is + function \?<\ (L, R : BIT_VECTOR) return BIT is + begin + if L < R then + return '1'; + else + return '0'; + end if; + end function \?<\; + -- %%% end function "?<"; + -- %%% function "?<=" (L, R : BIT_VECTOR) return BIT is + function \?<=\ (L, R : BIT_VECTOR) return BIT is + begin + if L <= R then + return '1'; + else + return '0'; + end if; + end function \?<=\; + -- %%% end function "?<="; + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + function "and" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) and r; + end loop; + return result; + end function "and"; + ------------------------------------------------------------------- + function "and" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l and rv(i); + end loop; + return result; + end function "and"; + + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + function "nand" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := not (lv(i) and r); + end loop; + return result; + end function "nand"; + ------------------------------------------------------------------- + function "nand" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := not (l and rv(i)); + end loop; + return result; + end function "nand"; + + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + function "or" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) or r; + end loop; + return result; + end function "or"; + ------------------------------------------------------------------- + function "or" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l or rv(i); + end loop; + return result; + end function "or"; + + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + function "nor" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := not (lv(i) or r); + end loop; + return result; + end function "nor"; + ------------------------------------------------------------------- + function "nor" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := not (l or rv(i)); + end loop; + return result; + end function "nor"; + + ------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + function "xor" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) xor r; + end loop; + return result; + end function "xor"; + ------------------------------------------------------------------- + function "xor" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l xor rv(i); + end loop; + return result; + end function "xor"; + + ------------------------------------------------------------------- + -- xnor + ------------------------------------------------------------------- + function "xnor" (l : BIT_VECTOR; r : BIT) return BIT_VECTOR is + alias lv : BIT_VECTOR (1 to l'length) is l; + variable result : BIT_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := not (lv(i) xor r); + end loop; + return result; + end function "xnor"; + ------------------------------------------------------------------- + function "xnor" (l : BIT; r : BIT_VECTOR) return BIT_VECTOR is + alias rv : BIT_VECTOR (1 to r'length) is r; + variable result : BIT_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := not (l xor rv(i)); + end loop; + return result; + end function "xnor"; + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + function "and" (l : BOOLEAN_VECTOR; r : BOOLEAN) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) and r; + end loop; + return result; + end function "and"; + ------------------------------------------------------------------- + function "and" (l : BOOLEAN; r : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l and rv(i); + end loop; + return result; + end function "and"; + + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + function "nand" (l : BOOLEAN_VECTOR; r : BOOLEAN) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := not (lv(i) and r); + end loop; + return result; + end function "nand"; + ------------------------------------------------------------------- + function "nand" (l : BOOLEAN; r : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := not (l and rv(i)); + end loop; + return result; + end function "nand"; + + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + function "or" (l : BOOLEAN_VECTOR; r : BOOLEAN) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) or r; + end loop; + return result; + end function "or"; + ------------------------------------------------------------------- + function "or" (l : BOOLEAN; r : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l or rv(i); + end loop; + return result; + end function "or"; + + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + function "nor" (l : BOOLEAN_VECTOR; r : BOOLEAN) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := not (lv(i) or r); + end loop; + return result; + end function "nor"; + ------------------------------------------------------------------- + function "nor" (l : BOOLEAN; r : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := not (l or rv(i)); + end loop; + return result; + end function "nor"; + + ------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + function "xor" (l : BOOLEAN_VECTOR; r : BOOLEAN) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := lv(i) xor r; + end loop; + return result; + end function "xor"; + ------------------------------------------------------------------- + function "xor" (l : BOOLEAN; r : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := l xor rv(i); + end loop; + return result; + end function "xor"; + + ------------------------------------------------------------------- + -- xnor + ------------------------------------------------------------------- + function "xnor" (l : BOOLEAN_VECTOR; r : BOOLEAN) return BOOLEAN_VECTOR is + alias lv : BOOLEAN_VECTOR (1 to l'length) is l; + variable result : BOOLEAN_VECTOR (1 to l'length); + begin + for i in result'range loop + result(i) := not (lv(i) xor r); + end loop; + return result; + end function "xnor"; + ------------------------------------------------------------------- + function "xnor" (l : BOOLEAN; r : BOOLEAN_VECTOR) return BOOLEAN_VECTOR is + alias rv : BOOLEAN_VECTOR (1 to r'length) is r; + variable result : BOOLEAN_VECTOR (1 to r'length); + begin + for i in result'range loop + result(i) := not (l xor rv(i)); + end loop; + return result; + end function "xnor"; + + -- Function from Proposal FT18 + function "and" (L : BIT; R : BOOLEAN) return BIT is + begin + if R then + return L; + else + return '0'; + end if; + end function "and"; + function "and" (L : BOOLEAN; R : BIT) return BIT is + begin + if L then + return R; + else + return '0'; + end if; + end function "and"; + function "or" (L : BIT; R : BOOLEAN) return BIT is + begin + if R then + return '1'; + else + return L; + end if; + end function "or"; + function "or" (L : BOOLEAN; R : BIT) return BIT is + begin + if L then + return '1'; + else + return R; + end if; + end function "or"; + function "xor" (L : BIT; R : BOOLEAN) return BIT is + begin + if R then + return not L; + else + return L; + end if; + end function "xor"; + function "xor" (L : BOOLEAN; R : BIT) return BIT is + begin + if L then + return not R; + else + return R; + end if; + end function "xor"; + function "nand" (L : BIT; R : BOOLEAN) return BIT is + begin + if R then + return not L; + else + return '1'; + end if; + end function "nand"; + function "nand" (L : BOOLEAN; R : BIT) return BIT is + begin + if L then + return not R; + else + return '1'; + end if; + end function "nand"; + function "nor" (L : BIT; R : BOOLEAN) return BIT is + begin + if R then + return '0'; + else + return not L; + end if; + end function "nor"; + function "nor" (L : BOOLEAN; R : BIT) return BIT is + begin + if L then + return '0'; + else + return not R; + end if; + end function "nor"; + function "xnor" (L : BIT; R : BOOLEAN) return BIT is + begin + if R then + return L; + else + return not L; + end if; + end function "xnor"; + function "xnor" (L : BOOLEAN; R : BIT) return BIT is + begin + if L then + return R; + else + return not R; + end if; + end function "xnor"; + + ------------------------------------------------------------------- + -- edge detection + ------------------------------------------------------------------- + function rising_edge (signal s : BIT) return BOOLEAN is + begin + return (s'event and (s = '1') and (s'last_value = '0')); + end function rising_edge; + + function falling_edge (signal s : BIT) return BOOLEAN is + begin + return (s'event and (s = '0') and (s'last_value = '1')); + end function falling_edge; + +end package body standard_additions; diff --git a/lib/Standard/ieee/add/standard_textio_additions_c.vhd b/lib/Standard/ieee/add/standard_textio_additions_c.vhd new file mode 100644 index 0000000..228545e --- /dev/null +++ b/lib/Standard/ieee/add/standard_textio_additions_c.vhd @@ -0,0 +1,1417 @@ +------------------------------------------------------------------------------ +-- "standard_textio_additions" package contains the additions to the built in +-- "standard.textio" package. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee_proposed.standard_textio_additions.all; +-- Last Modified: $Date: 2005-07-22 14:29:19-04 $ +-- RCS ID: $Id: standard_textio_additions_c.vhd,v 1.3 2005-07-22 14:29:19-04 l435385 Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +use work.standard_additions.all; -- %%% For testing only. +use std.textio.all; -- %%% For testing only. +package standard_textio_additions is + -- pragma synthesis_off + -- Writes L to a file and to the OUTPUT. Similar to the UNIX tee command + procedure tee (FILE F : TEXT; variable L : inout LINE); + + -- Read and Write procedure for strings + -- token based string read. STRLEN = 0 if the String read is bad + procedure SREAD (L : inout LINE; VALUE : out STRING; STRLEN : out natural); + -- alias SWRITE is WRITE [LINE, STRING, SIDE, WIDTH]; + procedure SWRITE (L : inout LINE; VALUE : in STRING; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + -- Read and Write procedures for Hexadecimal values + procedure HREAD (L : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN); + procedure HREAD (L : inout LINE; VALUE : out BIT_VECTOR); + + procedure HWRITE (L : inout LINE; VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + -- Read and Write procedures for Octal values + procedure OREAD (L : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN); + procedure OREAD (L : inout LINE; VALUE : out BIT_VECTOR); + + procedure OWRITE (L : inout LINE; VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + -- Read and Write procedures for Binary values +-- alias BREAD is READ [LINE, BIT_VECTOR, BOOLEAN]; +-- alias BREAD is READ [LINE, BIT_VECTOR]; +-- alias BWRITE is WRITE [LINE, BIT_VECTOR, SIDE, WIDTH]; + procedure BREAD (L : inout LINE; VALUE : out BIT_VECTOR; GOOD : out BOOLEAN); + procedure BREAD (L : inout LINE; VALUE : out BIT_VECTOR); + procedure BWRITE (L : inout LINE; VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + + -- read and write for vector versions + -- These versions produce "value1, value2, value3 ...." + procedure read (L : inout LINE; VALUE : out boolean_vector; + GOOD : out BOOLEAN); + procedure read (L : inout LINE; VALUE : out boolean_vector); + procedure write (L : inout LINE; VALUE : in boolean_vector; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + procedure read (L : inout LINE; VALUE : out integer_vector; + GOOD : out BOOLEAN); + procedure read (L : inout LINE; VALUE : out integer_vector); + procedure write (L : inout LINE; VALUE : in integer_vector; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0); + procedure read (L : inout LINE; VALUE : out real_vector; + GOOD : out BOOLEAN); + procedure read (L : inout LINE; VALUE : out real_vector); + procedure write (L : inout LINE; VALUE : in real_vector; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0; + DIGITS : in NATURAL := 0); + procedure read (L : inout LINE; VALUE : out time_vector; + GOOD : out BOOLEAN); + procedure read (L : inout LINE; VALUE : out time_vector); + procedure write (L : inout LINE; VALUE : in time_vector; + JUSTIFIED : in SIDE := right; FIELD : in WIDTH := 0; + UNIT : in TIME := ns); + + -- to_string routines + -- Justify a string left or right, for a given width + function justify ( + VALUE : in STRING; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) + return STRING; + -- Bit vector to string + function to_string ( + VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + -- bit_vector to binary string (alias) + alias to_bstring is to_string [BIT_VECTOR, SIDE, WIDTH return STRING]; + -- bit_vector to Hex string + function to_hstring ( + VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + -- bit_vector to Octal string + function to_ostring ( + VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + + -- to_string functions for the type from std.standard + function to_string ( + VALUE : in INTEGER; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + function to_string ( + VALUE : in BIT; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + function to_string ( + VALUE : in BOOLEAN; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + function to_string ( + VALUE : in SEVERITY_LEVEL; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + function to_string ( + VALUE : in FILE_OPEN_KIND; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + function to_string ( + VALUE : in FILE_OPEN_STATUS; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + function to_string ( + VALUE : in SIDE; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + -- returns number of digits, similar to write (REAL, SIDE, FIELD, DIGITS) + function to_string ( + VALUE : in REAL; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + DIGITS : in NATURAL := 0 + ) return STRING ; + -- Format is similar to the C printf format " " means real'image + -- Example to_string (3.14159, "%5.3f") returns "3.142" + function to_string ( + VALUE : in REAL; + format : in STRING + ) return STRING ; + -- Returns the time in the units specified. + -- similar to write (TIME, SIDE, FIELD, UNIT); + function to_string ( + VALUE : in TIME; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + UNIT : in TIME := ns + ) return STRING ; + + -- vector versions + function to_string ( + VALUE : in BOOLEAN_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + function to_string ( + VALUE : in INTEGER_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING ; + function to_string ( + VALUE : in REAL_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + DIGITS : in NATURAL := 0 + ) return STRING ; + function to_string ( + VALUE : in REAL_VECTOR; + format : in STRING + ) return STRING ; + function to_string ( + VALUE : in TIME_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + UNIT : in TIME := ns + ) return STRING ; + +-- pragma synthesis_on + -- Will be implicit + function minimum (L, R : SIDE) return SIDE; + function maximum (L, R : SIDE) return SIDE; +end package standard_textio_additions; + +package body standard_textio_additions is +-- pragma synthesis_off + constant NUS : STRING(2 to 1) := (others => ' '); -- NULL array + constant NBSP : CHARACTER := CHARACTER'val(160); -- space character + + -- Writes L to a file without modifying the contents of the line + procedure tee (file F : TEXT; variable L : inout LINE) is + begin + write (OUTPUT, L.all & NL); + writeline(F, L); + end procedure tee; + + -- Read and Write procedure for strings + procedure SREAD (L : inout LINE; + VALUE : out STRING; + STRLEN : out natural) is + variable ok : BOOLEAN; + variable c : CHARACTER; + -- Result is padded with space characters + variable result : STRING (1 to VALUE'length) := (others => ' '); + begin + VALUE := result; + loop -- skip white space + read(L, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + STRLEN := 0; + return; + end if; + result (1) := c; + STRLEN := 1; + for i in 2 to VALUE'length loop + read(L, c, ok); + if (ok = false) or ((c = ' ') or (c = NBSP) or (c = HT)) then + exit; + else + result (i) := c; + end if; + STRLEN := i; + end loop; + VALUE := result; + end procedure SREAD; + + -- alias SWRITE is WRITE [LINE, STRING, SIDE, WIDTH]; + procedure SWRITE (L : inout LINE; + VALUE : in STRING; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + WRITE (L => L, + VALUE => VALUE, + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure SWRITE; + -- Hex Read and Write procedures for bit_vector. + -- Procedure only visible internally. + procedure Char2QuadBits (C : CHARACTER; + RESULT : out BIT_VECTOR(3 downto 0); + GOOD : out BOOLEAN; + ISSUE_ERROR : in BOOLEAN) is + begin + case c is + when '0' => result := x"0"; good := true; + when '1' => result := x"1"; good := true; + when '2' => result := x"2"; good := true; + when '3' => result := x"3"; good := true; + when '4' => result := x"4"; good := true; + when '5' => result := x"5"; good := true; + when '6' => result := x"6"; good := true; + when '7' => result := x"7"; good := true; + when '8' => result := x"8"; good := true; + when '9' => result := x"9"; good := true; + when 'A' | 'a' => result := x"A"; good := true; + when 'B' | 'b' => result := x"B"; good := true; + when 'C' | 'c' => result := x"C"; good := true; + when 'D' | 'd' => result := x"D"; good := true; + when 'E' | 'e' => result := x"E"; good := true; + when 'F' | 'f' => result := x"F"; good := true; + when others => + assert not ISSUE_ERROR report + "TEXTIO.HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)." severity error; + GOOD := false; + end case; + end procedure Char2QuadBits; + + procedure HREAD (L : inout LINE; + VALUE : out BIT_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : BIT_VECTOR (0 to ne*4 - 1) := (others => '0'); + variable s : STRING(1 to ne-1); + begin + VALUE (VALUE'range) := (others => '0'); + loop -- skip white space + read(l, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + GOOD := false; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, false); + if not ok then + GOOD := false; + return; + end if; + read(L, s, ok); + if not ok then + GOOD := false; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, false); + if not ok then + GOOD := false; + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then + GOOD := false; -- vector was truncated. + else + GOOD := true; + VALUE := sv (pad to sv'high); + end if; + end procedure HREAD; + + procedure HREAD (L : inout LINE; + VALUE : out BIT_VECTOR) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : BIT_VECTOR(0 to ne*4 - 1) := (others => '0'); + variable s : STRING(1 to ne-1); + begin + VALUE (VALUE'range) := (others => '0'); + loop -- skip white space + read(l, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "TEXTIO.HREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, true); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "TEXTIO.HREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, true); + if not ok then + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then + report "TEXTIO.HREAD Error: Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end procedure HREAD; + + procedure HWRITE (L : inout LINE; + VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + write (L => L, + VALUE => to_hstring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure HWRITE; + + -- Procedure only visible internally. + procedure Char2TriBits (C : CHARACTER; + RESULT : out BIT_VECTOR(2 downto 0); + GOOD : out BOOLEAN; + ISSUE_ERROR : in BOOLEAN) is + begin + case c is + when '0' => result := o"0"; good := true; + when '1' => result := o"1"; good := true; + when '2' => result := o"2"; good := true; + when '3' => result := o"3"; good := true; + when '4' => result := o"4"; good := true; + when '5' => result := o"5"; good := true; + when '6' => result := o"6"; good := true; + when '7' => result := o"7"; good := true; + when others => + assert not ISSUE_ERROR + report + "TEXTIO.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + GOOD := false; + end case; + end procedure Char2TriBits; + + -- Read and Write procedures for Octal values + procedure OREAD (L : inout LINE; + VALUE : out BIT_VECTOR; + GOOD : out BOOLEAN) is + variable ok : BOOLEAN; + variable c : CHARACTER; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : BIT_VECTOR(0 to ne*3 - 1) := (others => '0'); + variable s : STRING(1 to ne-1); + begin + VALUE (VALUE'range) := (others => '0'); + loop -- skip white space + read(l, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + GOOD := false; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, false); + if not ok then + GOOD := false; + return; + end if; + read(L, s, ok); + if not ok then + GOOD := false; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, false); + if not ok then + GOOD := false; + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then + GOOD := false; -- vector was truncated. + else + GOOD := true; + VALUE := sv (pad to sv'high); + end if; + end procedure OREAD; + + procedure OREAD (L : inout LINE; + VALUE : out BIT_VECTOR) is + variable c : CHARACTER; + variable ok : BOOLEAN; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : BIT_VECTOR(0 to ne*3 - 1) := (others => '0'); + variable s : STRING(1 to ne-1); + begin + VALUE (VALUE'range) := (others => '0'); + loop -- skip white space + read(l, c, ok); + exit when (ok = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "TEXTIO.OREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, true); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "TEXTIO.OREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, true); + if not ok then + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then + report "TEXTIO.OREAD Error: Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end procedure OREAD; + + procedure OWRITE (L : inout LINE; + VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + write (L => L, + VALUE => to_ostring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure OWRITE; + + -- Read and Write procedures for Binary values + -- alias BREAD is READ [LINE, BIT_VECTOR, BOOLEAN]; + -- alias BREAD is READ [LINE, BIT_VECTOR]; + -- alias BWRITE is WRITE [LINE, BIT_VECTOR, SIDE, WIDTH]; + procedure BREAD (L : inout LINE; + VALUE : out BIT_VECTOR; + GOOD : out BOOLEAN) is + begin + read (L => L, + VALUE => VALUE, + GOOD => GOOD); + end procedure BREAD; + procedure BREAD (L : inout LINE; + VALUE : out BIT_VECTOR) is + begin + read (L => L, + VALUE => VALUE); + end procedure BREAD; + -- alias BWRITE + procedure BWRITE (L : inout LINE; + VALUE : in BIT_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + write (L => L, + VALUE => VALUE, + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure BWRITE; + + -- read and write for vector versions + -- These versions produce "value1, value2, value3 ...." + procedure read (L : inout LINE; + VALUE : out boolean_vector; + GOOD : out BOOLEAN) is + variable dummy : CHARACTER; + variable igood : BOOLEAN := true; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + GOOD => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + good := false; + return; + end if; + end loop; + good := true; + end procedure read; + procedure read (L : inout LINE; + VALUE : out boolean_vector) is + variable dummy : CHARACTER; + variable igood : BOOLEAN; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + good => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + report "STANDARD.STD_TEXTIO(BOOLEAN_VECTOR) " + & "Read error ecounted during vector read" severity error; + return; + end if; + end loop; + end procedure read; + procedure write (L : inout LINE; + VALUE : in boolean_vector; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + for i in VALUE'range loop + write (L => L, + VALUE => VALUE(i), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + if (i /= value'right) then + swrite (L, ", "); + end if; + end loop; + end procedure write; + procedure read (L : inout LINE; + VALUE : out integer_vector; + GOOD : out BOOLEAN) is + variable dummy : CHARACTER; + variable igood : BOOLEAN := true; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + GOOD => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + good := false; + return; + end if; + end loop; + good := true; + end procedure read; + procedure read (L : inout LINE; + VALUE : out integer_vector) is + variable dummy : CHARACTER; + variable igood : BOOLEAN; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + good => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + report "STANDARD.STD_TEXTIO(INTEGER_VECTOR) " + & "Read error ecounted during vector read" severity error; + return; + end if; + end loop; + end procedure read; + procedure write (L : inout LINE; + VALUE : in integer_vector; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin + for i in VALUE'range loop + write (L => L, + VALUE => VALUE(i), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + if (i /= value'right) then + swrite (L, ", "); + end if; + end loop; + end procedure write; + procedure read (L : inout LINE; + VALUE : out real_vector; + GOOD : out BOOLEAN) is + variable dummy : CHARACTER; + variable igood : BOOLEAN := true; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + GOOD => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + good := false; + return; + end if; + end loop; + good := true; + end procedure read; + procedure read (L : inout LINE; + VALUE : out real_vector) is + variable dummy : CHARACTER; + variable igood : BOOLEAN; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + good => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + report "STANDARD.STD_TEXTIO(REAL_VECTOR) " + & "Read error ecounted during vector read" severity error; + return; + end if; + end loop; + end procedure read; + procedure write (L : inout LINE; + VALUE : in real_vector; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + DIGITS : in NATURAL := 0) is + begin + for i in VALUE'range loop + write (L => L, + VALUE => VALUE(i), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD, + DIGITS => DIGITS); + if (i /= value'right) then + swrite (L, ", "); + end if; + end loop; + end procedure write; + procedure read (L : inout LINE; + VALUE : out time_vector; + GOOD : out BOOLEAN) is + variable dummy : CHARACTER; + variable igood : BOOLEAN := true; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + GOOD => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + good := false; + return; + end if; + end loop; + good := true; + end procedure read; + procedure read (L : inout LINE; + VALUE : out time_vector) is + variable dummy : CHARACTER; + variable igood : BOOLEAN; + begin + for i in VALUE'range loop + read (L => L, + VALUE => VALUE(i), + good => igood); + if (igood) and (i /= value'right) then + read (L => L, + VALUE => dummy, -- Toss the comma or seperator + good => igood); + end if; + if (not igood) then + report "STANDARD.STD_TEXTIO(TIME_VECTOR) " + & "Read error ecounted during vector read" severity error; + return; + end if; + end loop; + end procedure read; + procedure write (L : inout LINE; + VALUE : in time_vector; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + UNIT : in TIME := ns) is + begin + for i in VALUE'range loop + write (L => L, + VALUE => VALUE(i), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD, + UNIT => UNIT); + if (i /= value'right) then + swrite (L, ", "); + end if; + end loop; + end procedure write; + +------------------------------------------------------------------- +-- TO_STRING +------------------------------------------------------------------- + function justify ( + value : in STRING; + justified : in SIDE := right; + field : in width := 0) + return STRING is + constant VAL_LEN : INTEGER := value'length; + variable result : STRING (1 to field) := (others => ' '); + begin -- function justify + -- return value if field is too small + if VAL_LEN >= field then + return value; + end if; + if justified = left then + result(1 to VAL_LEN) := value; + elsif justified = right then + result(field - VAL_LEN + 1 to field) := value; + end if; + return result; + end function justify; + + ----------------------------------------------------------------------------- + -- to_string funcitons for bit_vector + ----------------------------------------------------------------------------- + function to_string ( + value : in BIT_VECTOR; + justified : in SIDE := right; + field : in width := 0 + ) return STRING is + alias ivalue : BIT_VECTOR(1 to value'length) is value; + variable result : STRING(1 to value'length); + begin + if value'length < 1 then + return NUS; + else + for i in ivalue'range loop + if iValue(i) = '0' then + result(i) := '0'; + else + result(i) := '1'; + end if; + end loop; + return justify(result, justified, field); + end if; + end function to_string; + + -- alias to_bstring is to_string [BIT_VECTOR, SIDE, WIDTH return STRING]; + ------------------------------------------------------------------- + -- TO_HSTRING + ------------------------------------------------------------------- + function to_hstring ( + value : in BIT_VECTOR; + justified : in SIDE := right; + field : in width := 0 + ) return STRING is + constant ne : INTEGER := (value'length+3)/4; + constant pad : BIT_VECTOR(0 to (ne*4 - value'length) - 1) := (others => '0'); + variable ivalue : BIT_VECTOR(0 to ne*4 - 1); + variable result : STRING(1 to ne); + variable quad : BIT_VECTOR(0 to 3); + begin + if value'length < 1 then + return NUS; + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + quad := ivalue(4*i to 4*i+3); + case quad is + when x"0" => result(i+1) := '0'; + when x"1" => result(i+1) := '1'; + when x"2" => result(i+1) := '2'; + when x"3" => result(i+1) := '3'; + when x"4" => result(i+1) := '4'; + when x"5" => result(i+1) := '5'; + when x"6" => result(i+1) := '6'; + when x"7" => result(i+1) := '7'; + when x"8" => result(i+1) := '8'; + when x"9" => result(i+1) := '9'; + when x"A" => result(i+1) := 'A'; + when x"B" => result(i+1) := 'B'; + when x"C" => result(i+1) := 'C'; + when x"D" => result(i+1) := 'D'; + when x"E" => result(i+1) := 'E'; + when x"F" => result(i+1) := 'F'; + end case; + end loop; + return justify(result, justified, field); + end function to_hstring; + + ------------------------------------------------------------------- + -- TO_OSTRING + ------------------------------------------------------------------- + function to_ostring ( + value : in BIT_VECTOR; + justified : in SIDE := right; + field : in width := 0 + ) return STRING is + constant ne : INTEGER := (value'length+2)/3; + constant pad : BIT_VECTOR(0 to (ne*3 - value'length) - 1) := (others => '0'); + variable ivalue : BIT_VECTOR(0 to ne*3 - 1); + variable result : STRING(1 to ne); + variable tri : BIT_VECTOR(0 to 2); + begin + if value'length < 1 then + return NUS; + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + tri := ivalue(3*i to 3*i+2); + case tri is + when o"0" => result(i+1) := '0'; + when o"1" => result(i+1) := '1'; + when o"2" => result(i+1) := '2'; + when o"3" => result(i+1) := '3'; + when o"4" => result(i+1) := '4'; + when o"5" => result(i+1) := '5'; + when o"6" => result(i+1) := '6'; + when o"7" => result(i+1) := '7'; + end case; + end loop; + return justify(result, justified, field); + end function to_ostring; + + ----------------------------------------------------------------------------- + -- To_string for integer, real, boolean, etc. + ----------------------------------------------------------------------------- + function to_string ( + VALUE : in INTEGER; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + begin + return justify (value => INTEGER'image(VALUE), + justified => JUSTIFIED, + field => FIELD); + end function to_string; + + function to_string ( + VALUE : in BIT; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + variable result : STRING(1 to 1); + begin + if (value = '0') then + result := "0"; + else + result := "1"; + end if; + return justify(value => result, + justified => JUSTIFIED, + field => FIELD); + end function to_string; + + function to_string ( + VALUE : in BOOLEAN; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + begin + return justify(value => BOOLEAN'image(VALUE), + justified => JUSTIFIED, + field => FIELD); + end function to_string; + + function to_string ( + VALUE : in SEVERITY_LEVEL; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + begin + return justify(value => SEVERITY_LEVEL'image(VALUE), + justified => JUSTIFIED, + field => FIELD); + end function to_string; + + function to_string ( + VALUE : in FILE_OPEN_KIND; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + begin + return justify(value => FILE_OPEN_KIND'image(VALUE), + justified => JUSTIFIED, + field => FIELD); + end function to_string; + + function to_string ( + VALUE : in FILE_OPEN_STATUS; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + begin + return justify(value => FILE_OPEN_STATUS'image(VALUE), + justified => JUSTIFIED, + field => FIELD); + end function to_string; + + function to_string ( + VALUE : in SIDE; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + begin + return justify(value => SIDE'image(VALUE), + justified => JUSTIFIED, + field => FIELD); + end function to_string; + + function to_string ( + VALUE : in REAL; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + DIGITS : in NATURAL := 0 + ) return STRING is + begin + if (DIGITS /= 0) then + return justify (value => to_string (VALUE, "%1." + & integer'image(DIGITS) + & "f"), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + else + return justify (value => REAL'image(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end if; + end function to_string; + + -- %%% Remove this funciton (will be implicit in vhdl 200x + function maximum (l, r : integer) + return integer is + begin -- function maximum + if L > R then return L; + else return R; + end if; + end function maximum; + + function to_string ( + VALUE : in REAL; +-- JUSTIFIED : SIDE := right; +-- FIELD : WIDTH := 0; + format : in STRING -- %f6.2 + ) return STRING is + constant czero : CHARACTER := '0'; -- zero + constant half : REAL := 0.4999999999; -- almost 0.5 + -- Log10 funciton + function log10 (arg : real) return integer is + variable i : integer := 1; + begin + if ((arg = 0.0)) then + return 0; + elsif arg >= 1.0 then + while arg >= 10.0**i loop + i := i + 1; + end loop; + return (i-1); + else + while arg < 10.0**i loop + i := i - 1; + end loop; + return i; + end if; + end function log10; + -- purpose: writes a fractional real number into a line + procedure writefrc ( + variable L : inout LINE; -- LINE + variable cdes : in CHARACTER; + variable precision : in INTEGER; -- number of decimal places + variable value : in REAL) is -- real value + variable rvar : REAL; -- temp variable + variable xint : INTEGER; + variable xreal : REAL; + begin + xreal := (10.0**(-precision)); + write (L, '.'); + rvar := value; + for i in 1 to precision loop + rvar := rvar * 10.0; + xint := integer(rvar-0.49999999999); -- round + write (L, xint); + rvar := rvar - real(xint); + xreal := xreal * 10.0; + if (cdes = 'g') and (rvar < xreal) then + exit; + end if; + end loop; + end procedure writefrc; + -- purpose: replace the "." with a "@", and "e" with "j" to get around + -- read ("6.") and read ("2e") issues. + function subdot ( + constant format : STRING) + return STRING is + variable result : STRING (format'range); + begin + for i in format'range loop + if (format(i) = '.') then + result(i) := '@'; -- Because the parser reads 6.2 as REAL + elsif (format(i) = 'e') then + result(i) := 'j'; -- Because the parser read 2e as REAL + elsif (format(i) = 'E') then + result(i) := 'J'; -- Because the parser reads 2E as REAL + else + result(i) := format(i); + end if; + end loop; + return result; + end function subdot; + -- purpose: find a . in a STRING + function isdot ( + constant format : STRING) + return BOOLEAN is + begin + for i in format'range loop + if (format(i) = '@') then + return true; + end if; + end loop; + return false; + end function isdot; + variable exp : INTEGER; -- integer version of baseexp + variable bvalue : REAL; -- base value + variable roundvar, tvar : REAL; -- Rounding values + variable frcptr : INTEGER; -- integer version of number + variable fwidth, dwidth : INTEGER; -- field width and decimal width + variable dash, dot : BOOLEAN := false; + variable cdes, ddes : CHARACTER := ' '; + variable L : LINE; -- line type + begin + -- Perform the same function that "printf" does + -- examples "%6.2f" "%-7e" "%g" + if not (format(format'left) = '%') then + report "to_string: Illegal format string """ & format & '"' + severity error; + return ""; + end if; + L := new string'(subdot(format)); + read (L, ddes); -- toss the '%' + case L.all(1) is + when '-' => dash := true; + when '@' => dash := true; -- in FP, a "-" and a "." are the same + when 'f' => cdes := 'f'; + when 'F' => cdes := 'F'; + when 'g' => cdes := 'g'; + when 'G' => cdes := 'G'; + when 'j' => cdes := 'e'; -- parser reads 5e as real, thus we sub j + when 'J' => cdes := 'E'; + when '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => null; + when others => + report "to_string: Illegal format string """ & format & '"' + severity error; + return ""; + end case; + if (dash or (cdes /= ' ')) then + read (L, ddes); -- toss the next character + end if; + if (cdes = ' ') then + if (isdot(L.all)) then -- if you see a . two numbers + read (L, fwidth); -- read field width + read (L, ddes); -- toss the next character . + read (L, dwidth); -- read decimal width + else + read (L, fwidth); -- read field width + dwidth := 6; -- the default decimal width is 6 + end if; + read (L, cdes); + if (cdes = 'j') then + cdes := 'e'; -- because 2e reads as "REAL". + elsif (cdes = 'J') then + cdes := 'E'; + end if; + else + if (cdes = 'E' or cdes = 'e') then + fwidth := 10; -- default for e and E is %10.6e + else + fwidth := 0; -- default for f and g is %0.6f + end if; + dwidth := 6; + end if; + deallocate (L); -- reclame the pointer L. +-- assert (not debug) report "Format: " & format & " " +-- & INTEGER'image(fwidth) & "." & INTEGER'image(dwidth) & cdes +-- severity note; + if (not (cdes = 'f' or cdes = 'F' or cdes = 'g' or cdes = 'G' + or cdes = 'e' or cdes = 'E')) then + report "to_string: Illegal format """ & format & '"' severity error; + return ""; + end if; + if (VALUE < 0.0) then + bvalue := -value; + write (L, '-'); + else + bvalue := value; + end if; + case cdes is + when 'e' | 'E' => -- 7.000E+01 + exp := log10(bvalue); + roundvar := half*(10.0**(exp-dwidth)); + bvalue := bvalue + roundvar; -- round + exp := log10(bvalue); -- because we CAN overflow + bvalue := bvalue * (10.0**(-exp)); -- result is D.XXXXXX + frcptr := integer(bvalue-half); -- Write a single digit. + write (L, frcptr); + bvalue := bvalue - real(frcptr); + writefrc ( -- Write out the fraction + L => L, + cdes => cdes, + precision => dwidth, + value => bvalue); + write (L, cdes); -- e or E + if (exp < 0) then + write (L, '-'); + else + write (L, '+'); + end if; + exp := abs(exp); + if (exp < 10) then -- we need another "0". + write (L, czero); + end if; + write (L, exp); + when 'f' | 'F' => -- 70.0 + exp := log10(bvalue); + roundvar := half*(10.0**(-dwidth)); + bvalue := bvalue + roundvar; -- round + exp := log10(bvalue); -- because we CAN overflow + if (exp < 0) then -- 0.X case + write (L, czero); + else -- loop because real'high > integer'high + while (exp >= 0) loop + frcptr := integer(bvalue * (10.0**(-exp)) - half); + write (L, frcptr); + bvalue := bvalue - (real(frcptr) * (10.0**exp)); + exp := exp-1; + end loop; + end if; + writefrc ( + L => L, + cdes => cdes, + precision => dwidth, + value => bvalue); + when 'g' | 'G' => -- 70 + exp := log10(bvalue); + roundvar := half*(10.0**(exp-dwidth)); -- small number + bvalue := bvalue + roundvar; -- round + exp := log10(bvalue); -- because we CAN overflow + frcptr := integer(bvalue-half); + tvar := bvalue-roundvar - real(frcptr); -- even smaller number + if (exp < dwidth) + and (tvar < roundvar and tvar > -roundvar) then +-- and ((bvalue-roundvar) = real(frcptr)) then + write (L, frcptr); -- Just a short integer, write it. + elsif (exp >= dwidth) or (exp < -4) then + -- in "e" format (modified) + bvalue := bvalue * (10.0**(-exp)); -- result is D.XXXXXX + frcptr := integer(bvalue-half); + write (L, frcptr); + bvalue := bvalue - real(frcptr); + if (bvalue > (10.0**(1-dwidth))) then + dwidth := dwidth - 1; + writefrc ( + L => L, + cdes => cdes, + precision => dwidth, + value => bvalue); + end if; + if (cdes = 'G') then + write (L, 'E'); + else + write (L, 'e'); + end if; + if (exp < 0) then + write (L, '-'); + else + write (L, '+'); + end if; + exp := abs(exp); + if (exp < 10) then + write (L, czero); + end if; + write (L, exp); + else + -- in "f" format (modified) + if (exp < 0) then + write (L, czero); + dwidth := maximum (dwidth, 4); -- if exp < -4 or > precision. + bvalue := bvalue - roundvar; -- recalculate rounding + roundvar := half*(10.0**(-dwidth)); + bvalue := bvalue + roundvar; + else + write (L, frcptr); -- integer part (always small) + bvalue := bvalue - (real(frcptr)); + dwidth := dwidth - exp - 1; + end if; + if (bvalue > roundvar) then + writefrc ( + L => L, + cdes => cdes, + precision => dwidth, + value => bvalue); + end if; + end if; + when others => return ""; + end case; + -- You don't truncate real numbers. +-- if (dot) then -- truncate +-- if (L.all'length > fwidth) then +-- return justify (value => L.all (1 to fwidth), +-- justified => RIGHT, +-- field => fwidth); +-- else +-- return justify (value => L.all, +-- justified => RIGHT, +-- field => fwidth); +-- end if; + if (dash) then -- fill to fwidth + return justify (value => L.all, + justified => LEFT, + field => fwidth); + else + return justify (value => L.all, + justified => RIGHT, + field => fwidth); + end if; + end function to_string; + + -- if the time is 1 ns, and the unit is 1 ps, + -- then to_string(now) = 1000.0 ps; + function to_string ( + VALUE : in TIME; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + UNIT : in TIME := ns + ) return STRING is + variable L : LINE; -- pointer + begin + deallocate (L); + write (L => L, + VALUE => VALUE, + JUSTIFIED => JUSTIFIED, + FIELD => FIELD, + UNIT => UNIT); + return L.all; + end function to_string; + + -- vector versions + function to_string ( + VALUE : in BOOLEAN_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + variable L : LINE; + begin + deallocate (L); + write (L => L, + VALUE => VALUE, + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + return L.all; + end function to_string; + function to_string ( + VALUE : in INTEGER_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0 + ) return STRING is + variable L : LINE; + begin + deallocate (L); + write (L => L, + VALUE => VALUE, + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + return L.all; + end function to_string; + function to_string ( + VALUE : in REAL_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + DIGITS : in NATURAL := 0 + ) return STRING is + variable L : LINE; + begin + deallocate (L); + write (L => L, + VALUE => VALUE, + JUSTIFIED => JUSTIFIED, + FIELD => FIELD, + DIGITS => DIGITS); + return L.all; + end function to_string; + function to_string ( + VALUE : in REAL_VECTOR; + format : in STRING + ) return STRING is + variable L : LINE; + begin + deallocate (L); + for i in VALUE'range loop + write (L => L, + VALUE => to_string (VALUE => VALUE(i), + format => format)); + if (i /= VALUE'right) then + SWRITE (L => L, + VALUE => ", "); + end if; + end loop; + return L.all; + end function to_string; + function to_string ( + VALUE : in TIME_VECTOR; + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0; + UNIT : in TIME := ns + ) return STRING is + variable L : LINE; + begin + deallocate (L); + write (L => L, + VALUE => VALUE, + JUSTIFIED => JUSTIFIED, + FIELD => FIELD, + UNIT => UNIT); + return L.all; + end function to_string; + + -- pragma synthesis_on + -- Will be implicit + function minimum (L, R : SIDE) return SIDE is + begin + if L > R then return R; + else return L; + end if; + end function minimum; + function maximum (L, R : SIDE) return SIDE is + begin + if L > R then return L; + else return R; + end if; + end function maximum; + +end package body standard_textio_additions; diff --git a/lib/Standard/ieee/add/std_logic_1164_additions.vhd b/lib/Standard/ieee/add/std_logic_1164_additions.vhd new file mode 100644 index 0000000..1573b2a --- /dev/null +++ b/lib/Standard/ieee/add/std_logic_1164_additions.vhd @@ -0,0 +1,2681 @@ +------------------------------------------------------------------------------ +-- "std_logic_1164_additions" package contains the additions to the standard +-- "std_logic_1164" package proposed by the VHDL-200X-ft working group. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee_proposed.std_logic_1164_additions.all; +-- Last Modified: $Date: 2006-03-22 15:52:00-05 $ +-- RCS ID: $Id: std_logic_1164_additions.vhd,v 1.7 2006-03-22 15:52:00-05 l435385 Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use std.textio.all; +package std_logic_1164_additions is + + -- new aliases +-- alias to_bv is ieee.std_logic_1164.To_bitvector [std_logic_vector, bit return bit_vector] ; +-- alias to_bv is ieee.std_logic_1164.To_bitvector [std_ulogic_vector, bit return bit_vector] ; +-- alias to_bit_vector is ieee.std_logic_1164.To_bitvector [std_logic_vector, bit return bit_vector] ; +-- alias to_bit_vector is ieee.std_logic_1164.To_bitvector [std_ulogic_vector, bit return bit_vector] ; +-- alias to_slv is ieee.std_logic_1164.To_StdLogicVector [BIT_VECTOR return std_logic_vector] ; +-- alias to_slv is ieee.std_logic_1164.To_StdLogicVector [std_ulogic_vector return std_logic_vector] ; +-- alias to_std_logic_vector is ieee.std_logic_1164.To_StdLogicVector [BIT_VECTOR return std_logic_vector] ; +-- alias to_std_logic_vector is ieee.std_logic_1164.To_StdLogicVector [std_ulogic_vector return std_logic_vector] ; +-- alias to_sulv is ieee.std_logic_1164.To_StdULogicVector [BIT_VECTOR return std_ulogic_vector] ; +-- alias to_sulv is ieee.std_logic_1164.To_StdULogicVector [std_logic_vector return std_ulogic_vector] ; +-- alias to_std_ulogic_vector is ieee.std_logic_1164.To_StdULogicVector [BIT_VECTOR return std_ulogic_vector] ; +-- alias to_std_ulogic_vector is ieee.std_logic_1164.To_StdULogicVector [std_logic_vector return std_ulogic_vector] ; + + -- Done as functions because some tools don't like the alias syntax + function to_bv ( s : std_logic_vector; xmap : BIT := '0') RETURN BIT_VECTOR; + function to_bv ( s : std_ulogic_vector; xmap : BIT := '0') RETURN BIT_VECTOR ; + function to_bit_vector ( s : std_logic_vector; xmap : BIT := '0') RETURN BIT_VECTOR; + function to_bit_vector ( s : std_ulogic_vector; xmap : BIT := '0') RETURN BIT_VECTOR; + function to_slv ( b : BIT_VECTOR ) RETURN std_logic_vector; + function to_slv ( s : std_ulogic_vector ) RETURN std_logic_vector ; + function to_std_logic_vector ( b : BIT_VECTOR ) RETURN std_logic_vector; + function to_std_logic_vector ( s : std_ulogic_vector ) RETURN std_logic_vector ; + function to_sulv ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + function to_sulv ( s : std_logic_vector ) RETURN std_ulogic_vector ; + function to_std_ulogic_vector ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + function to_std_ulogic_vector ( s : std_logic_vector ) RETURN std_ulogic_vector; + ------------------------------------------------------------------- + -- overloaded shift operators + ------------------------------------------------------------------- + + function "sll" ( l : std_logic_vector; r : integer ) RETURN std_logic_vector; + function "sll" ( l : std_ulogic_vector; r : integer ) RETURN std_ulogic_vector; + + function "srl" ( l : std_logic_vector; r : integer ) RETURN std_logic_vector; + function "srl" ( l : std_ulogic_vector; r : integer ) RETURN std_ulogic_vector; + + function "rol" ( l : std_logic_vector; r : integer ) RETURN std_logic_vector; + function "rol" ( l : std_ulogic_vector; r : integer ) RETURN std_ulogic_vector; + + function "ror" ( l : std_logic_vector; r : integer ) RETURN std_logic_vector; + function "ror" ( l : std_ulogic_vector; r : integer ) RETURN std_ulogic_vector; + ------------------------------------------------------------------- + -- vector/scalar overloaded logical operators + ------------------------------------------------------------------- + FUNCTION "and" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector; + FUNCTION "and" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector; + FUNCTION "and" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "and" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION "nand" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector; + FUNCTION "nand" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector; + FUNCTION "nand" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nand" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION "or" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector; + FUNCTION "or" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector; + FUNCTION "or" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "or" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION "nor" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector; + FUNCTION "nor" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector; + FUNCTION "nor" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nor" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION "xor" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector; + FUNCTION "xor" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector; + FUNCTION "xor" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "xor" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION "xnor" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector; + FUNCTION "xnor" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector; + FUNCTION "xnor" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "xnor" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector; + ----------------------------------------------------------------------------- + -- std_ulogic and boolean functions + ----------------------------------------------------------------------------- + function "and" (L: std_ulogic; R: boolean) return std_ulogic; + function "and" (L: boolean; R: std_ulogic) return std_ulogic; + function "or" (L: std_ulogic; R: boolean) return std_ulogic; + function "or" (L: boolean; R: std_ulogic) return std_ulogic; + function "xor" (L: std_ulogic; R: boolean) return std_ulogic; + function "xor" (L: boolean; R: std_ulogic) return std_ulogic; + function "nand" (L: std_ulogic; R: boolean) return std_ulogic; + function "nand" (L: boolean; R: std_ulogic) return std_ulogic; + function "nor" (L: std_ulogic; R: boolean) return std_ulogic; + function "nor" (L: boolean; R: std_ulogic) return std_ulogic; + function "xnor" (L: std_ulogic; R: boolean) return std_ulogic; + function "xnor" (L: boolean; R: std_ulogic) return std_ulogic; + ------------------------------------------------------------------- + -- vector-reduction functions. + -- "and" functions default to "1", or defaults to "0" + ------------------------------------------------------------------- + ----------------------------------------------------------------------------- + -- %%% Replace the "_reduce" functions with the ones commented out below. + ----------------------------------------------------------------------------- + -- function "and" ( arg : std_logic_vector ) RETURN std_ulogic; + -- function "and" ( arg : std_ulogic_vector ) RETURN std_ulogic; + -- function "nand" ( arg : std_logic_vector ) RETURN std_ulogic; + -- function "nand" ( arg : std_ulogic_vector ) RETURN std_ulogic; + -- function "or" ( arg : std_logic_vector ) RETURN std_ulogic; + -- function "or" ( arg : std_ulogic_vector ) RETURN std_ulogic; + -- function "nor" ( arg : std_logic_vector ) RETURN std_ulogic; + -- function "nor" ( arg : std_ulogic_vector ) RETURN std_ulogic; + -- function "xor" ( arg : std_logic_vector ) RETURN std_ulogic; + -- function "xor" ( arg : std_ulogic_vector ) RETURN std_ulogic; + -- function "xnor" ( arg : std_logic_vector ) RETURN std_ulogic; + -- function "xnor" ( arg : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION and_reduce ( arg : std_logic_vector ) RETURN std_ulogic; + FUNCTION and_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION nand_reduce ( arg : std_logic_vector ) RETURN std_ulogic; + FUNCTION nand_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION or_reduce ( arg : std_logic_vector ) RETURN std_ulogic; + FUNCTION or_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION nor_reduce ( arg : std_logic_vector ) RETURN std_ulogic; + FUNCTION nor_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION xor_reduce ( arg : std_logic_vector ) RETURN std_ulogic; + FUNCTION xor_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION xnor_reduce ( arg : std_logic_vector ) RETURN std_ulogic; + FUNCTION xnor_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic; + ------------------------------------------------------------------- + -- ?= operators, same functionality as 1076.3 1994 std_match + ------------------------------------------------------------------- +-- FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?=" ( l, r : std_logic_vector ) RETURN std_ulogic; +-- FUNCTION "?=" ( l, r : std_ulogic_vector ) RETURN std_ulogic; +-- FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?/=" ( l, r : std_logic_vector ) RETURN std_ulogic; +-- FUNCTION "?/=" ( l, r : std_ulogic_vector ) RETURN std_ulogic; +-- FUNCTION "?>" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?>" ( l, r : std_logic_vector ) RETURN std_ulogic; +-- FUNCTION "?>" ( l, r : std_ulogic_vector ) RETURN std_ulogic; +-- FUNCTION "?>=" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?>=" ( l, r : std_logic_vector ) RETURN std_ulogic; +-- FUNCTION "?>=" ( l, r : std_ulogic_vector ) RETURN std_ulogic; +-- FUNCTION "?<" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?<" ( l, r : std_logic_vector ) RETURN std_ulogic; +-- FUNCTION "?<" ( l, r : std_ulogic_vector ) RETURN std_ulogic; +-- FUNCTION "?<=" ( l, r : std_ulogic ) RETURN std_ulogic; +-- FUNCTION "?<=" ( l, r : std_logic_vector ) RETURN std_ulogic; +-- FUNCTION "?<=" ( l, r : std_ulogic_vector ) RETURN std_ulogic; + + FUNCTION \?=\ ( l, r : std_ulogic ) RETURN std_ulogic; + FUNCTION \?=\ ( l, r : std_logic_vector ) RETURN std_ulogic; + FUNCTION \?=\ ( l, r : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION \?/=\ ( l, r : std_ulogic ) RETURN std_ulogic; + FUNCTION \?/=\ ( l, r : std_logic_vector ) RETURN std_ulogic; + FUNCTION \?/=\ ( l, r : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION \?>\ ( l, r : std_ulogic ) RETURN std_ulogic; + FUNCTION \?>\ ( l, r : std_logic_vector ) RETURN std_ulogic; + FUNCTION \?>\ ( l, r : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION \?>=\ ( l, r : std_ulogic ) RETURN std_ulogic; + FUNCTION \?>=\ ( l, r : std_logic_vector ) RETURN std_ulogic; + FUNCTION \?>=\ ( l, r : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION \?<\ ( l, r : std_ulogic ) RETURN std_ulogic; + FUNCTION \?<\ ( l, r : std_logic_vector ) RETURN std_ulogic; + FUNCTION \?<\ ( l, r : std_ulogic_vector ) RETURN std_ulogic; + FUNCTION \?<=\ ( l, r : std_ulogic ) RETURN std_ulogic; + FUNCTION \?<=\ ( l, r : std_logic_vector ) RETURN std_ulogic; + FUNCTION \?<=\ ( l, r : std_ulogic_vector ) RETURN std_ulogic; + + -- "??" operator, converts a std_ulogic to a boolean. + --%%% Uncomment the following operators + -- FUNCTION "??" (S : STD_ULOGIC) RETURN BOOLEAN; + --%%% REMOVE the following funciton (for testing only) + FUNCTION \??\ (S : STD_ULOGIC) RETURN BOOLEAN; + + -- rtl_synthesis off + ----------------------------------------------------------------------------- + -- Read and Write functions copied from "std_logic_textio" + ----------------------------------------------------------------------------- + -- Read and Write procedures for STD_ULOGIC and STD_ULOGIC_VECTOR + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC; GOOD : out BOOLEAN); + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC); + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); + + procedure WRITE (L : inout LINE; VALUE : in STD_ULOGIC; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + + procedure WRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + + -- Read and Write procedures for STD_LOGIC_VECTOR + + procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN); + procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR); + + procedure WRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + +-- alias bread is read [line, STD_ULOGIC, BOOLEAN] ; +-- alias bread is read [line, STD_ULOGIC] ; +-- alias bread is read [line, STD_ULOGIC_VECTOR, BOOLEAN] ; +-- alias bread is read [line, STD_ULOGIC_VECTOR] ; +-- alias bread is read [line, STD_LOGIC_VECTOR, BOOLEAN] ; +-- alias bread is read [line, STD_LOGIC_VECTOR] ; +-- alias bwrite is write [line, STD_ULOGIC, side, width] ; +-- alias bwrite is write [line, STD_ULOGIC_VECTOR, side, width] ; +-- alias bwrite is write [line, STD_LOGIC_VECTOR, side, width] ; + + procedure BREAD (L : inout LINE; VALUE : out STD_ULOGIC; GOOD : out BOOLEAN); + procedure BREAD (L : inout LINE; VALUE : out STD_ULOGIC); + + procedure BREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); + procedure BREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); + procedure BREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN); + procedure BREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR); + procedure BWRITE (L : inout LINE; VALUE : in STD_ULOGIC; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + + procedure BWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + procedure BWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + + -- Read and Write procedures for Hex values + + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN); + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); + + procedure HWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + + procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN); + procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR); + + procedure HWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + + -- Read and Write procedures for Octal values + + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN); + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR); + + procedure OWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN); + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR); + + procedure OWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0); + -- rtl_synthesis on + -------------------------------------------------------------------------- + -- Converts a std_logic_vector or std_ulogic vector to a string. + -------------------------------------------------------------------------- + function to_string ( + value : in STD_ULOGIC; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + function to_string ( + value : in std_ulogic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + -- alias to_bstring is to_string [std_ulogic_vector, side, width return string]; + function to_bstring ( + value : in std_ulogic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + function to_hstring ( + value : in std_ulogic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + function to_ostring ( + value : in std_ulogic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string ; + + function to_string ( + value : in std_logic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + -- alias to_bstring is to_string [std_logic_vector, side, width return string]; + function to_bstring ( + value : in std_logic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + function to_hstring ( + value : in std_logic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string; + + function to_ostring ( + value : in std_logic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string ; + +end package std_logic_1164_additions; + +package body std_logic_1164_additions is + -- alias done as functions + function to_bv ( s : std_logic_vector; xmap : BIT := '0') + RETURN BIT_VECTOR is + begin + return To_bitvector (s, xmap); + end function to_bv; + function to_bv ( s : std_ulogic_vector; xmap : BIT := '0') + RETURN BIT_VECTOR is + begin + return To_bitvector (s, xmap); + end function to_bv; + function to_bit_vector ( s : std_logic_vector; xmap : BIT := '0') + RETURN BIT_VECTOR is + begin + return To_bitvector (s, xmap); + end function to_bit_vector; + function to_bit_vector ( s : std_ulogic_vector; xmap : BIT := '0') + RETURN BIT_VECTOR is + begin + return To_bitvector (s, xmap); + end function to_bit_vector; + function to_slv ( b : BIT_VECTOR ) + RETURN STD_LOGIC_VECTOR is + begin + return to_StdLogicVector (b); + end function to_slv; + function to_slv ( s : std_ulogic_vector ) + RETURN std_logic_vector is + begin + return to_StdLogicVector (s); + end function to_slv; + function to_std_logic_vector ( b : BIT_VECTOR ) + RETURN std_logic_vector is + begin + return to_StdLogicVector (b); + end function to_std_logic_vector; + function to_std_logic_vector ( s : std_ulogic_vector ) + RETURN std_logic_vector is + begin + return to_StdLogicVector (s); + end function to_std_logic_vector; + function to_sulv ( b : BIT_VECTOR ) + RETURN std_ulogic_vector is + begin + return to_StdULogicVector (b); + end function to_sulv; + function to_sulv ( s : std_logic_vector ) + RETURN std_ulogic_vector is + begin + return to_StdULogicVector (s); + end function to_sulv; + function to_std_ulogic_vector ( b : BIT_VECTOR ) + RETURN std_ulogic_vector is + begin + return to_StdULogicVector (b); + end function to_std_ulogic_vector; + function to_std_ulogic_vector ( s : std_logic_vector ) + RETURN std_ulogic_vector is + begin + return to_StdULogicVector (s); + end function to_std_ulogic_vector; + + TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; + ----------------------------------------------------------------------------- + -- New/updated funcitons for VHDL-200X fast track + ----------------------------------------------------------------------------- + ------------------------------------------------------------------- + -- overloaded shift operators + ------------------------------------------------------------------- + + ------------------------------------------------------------------- + -- sll + ------------------------------------------------------------------- + FUNCTION "sll" ( l : std_logic_vector; r : integer ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( l'RANGE ) := (OTHERS => '0'); + ALIAS resultv : std_logic_vector ( 1 TO l'LENGTH ) IS result; + BEGIN + IF r = 0 OR l'LENGTH = 0 THEN + RETURN l; + ELSIF r > 0 THEN + IF r < l'LENGTH THEN + resultv(1 TO l'LENGTH - r) := lv(r+1 TO l'LENGTH); + END IF; + RETURN result; + ELSE + RETURN l SRL (-r); + END IF; + END FUNCTION "sll"; + ------------------------------------------------------------------- + FUNCTION "sll" ( l : std_ulogic_vector; r : integer ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( l'RANGE ) := (OTHERS => '0'); + ALIAS resultv : std_ulogic_vector ( 1 TO l'LENGTH ) IS result; + BEGIN + IF r = 0 OR l'LENGTH = 0 THEN + RETURN l; + ELSIF r > 0 THEN + IF r < l'LENGTH THEN + resultv(1 TO l'LENGTH - r) := lv(r+1 TO l'LENGTH); + END IF; + RETURN result; + ELSE + RETURN l SRL (-r); + END IF; + END FUNCTION "sll"; + + ------------------------------------------------------------------- + -- srl + ------------------------------------------------------------------- + FUNCTION "srl" ( l : std_logic_vector; r : integer ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( l'RANGE ) := (OTHERS => '0'); + ALIAS resultv : std_logic_vector ( 1 TO l'LENGTH ) IS result; + BEGIN + IF r = 0 OR l'LENGTH = 0 THEN + RETURN l; + ELSIF r > 0 THEN + IF r < l'LENGTH THEN + resultv(r+1 TO l'LENGTH) := lv(1 TO l'LENGTH - r); + END IF; + RETURN result; + ELSE + RETURN l SLL (-r); + END IF; + END FUNCTION "srl"; + ------------------------------------------------------------------- + FUNCTION "srl" ( l : std_ulogic_vector; r : integer ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( l'RANGE ) := (OTHERS => '0'); + ALIAS resultv : std_ulogic_vector ( 1 TO l'LENGTH ) IS result; + BEGIN + IF r = 0 OR l'LENGTH = 0 THEN + RETURN l; + ELSIF r > 0 THEN + IF r < l'LENGTH THEN + resultv(r+1 TO l'LENGTH) := lv(1 TO l'LENGTH - r); + END IF; + RETURN result; + ELSE + RETURN l SLL (-r); + END IF; + END FUNCTION "srl"; + + ------------------------------------------------------------------- + -- rol + ------------------------------------------------------------------- + FUNCTION "rol" ( l : std_logic_vector; r : integer ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( l'RANGE ); + ALIAS resultv : std_logic_vector ( 1 TO l'LENGTH ) IS result; + VARIABLE rv : integer; + BEGIN + IF r = 0 OR l'LENGTH = 0 THEN + RETURN l; + ELSIF r > 0 THEN + rv := r MOD l'length; + resultv(1 TO l'LENGTH - rv ) := lv(rv+1 TO l'LENGTH); + resultv(l'LENGTH - rv + 1 TO l'length) := lv(1 TO rv); + RETURN result; + ELSE + RETURN l ROR (-r); + END IF; + END FUNCTION "rol"; + ------------------------------------------------------------------- + FUNCTION "rol" ( l : std_ulogic_vector; r : integer ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( l'RANGE ); + ALIAS resultv : std_ulogic_vector ( 1 TO l'LENGTH ) IS result; + VARIABLE rv : integer; + BEGIN + IF r = 0 OR l'LENGTH = 0 THEN + RETURN l; + ELSIF r > 0 THEN + rv := r MOD l'length; + resultv(1 TO l'LENGTH - rv ) := lv(rv+1 TO l'LENGTH); + resultv(l'LENGTH - rv + 1 TO l'LENGTH) := lv(1 TO rv); + RETURN result; + ELSE + RETURN l ROR (-r); + END IF; + END FUNCTION "rol"; + + ------------------------------------------------------------------- + -- ror + ------------------------------------------------------------------- + FUNCTION "ror" ( l : std_logic_vector; r : integer ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( l'RANGE ); + ALIAS resultv : std_logic_vector ( 1 TO l'LENGTH ) IS result; + VARIABLE rv : integer; + BEGIN + IF r = 0 OR l'LENGTH = 0 THEN + RETURN l; + ELSIF r > 0 THEN + rv := r MOD l'length; + resultv(rv+1 TO l'LENGTH) := lv(1 TO l'LENGTH - rv); + resultv(1 TO rv) := lv(l'LENGTH - rv + 1 TO l'LENGTH); + RETURN result; + ELSE + RETURN l ROL (-r); + END IF; + END FUNCTION "ror"; + ------------------------------------------------------------------- + FUNCTION "ror" ( l : std_ulogic_vector; r : integer ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( l'RANGE ); + ALIAS resultv : std_ulogic_vector ( 1 TO l'LENGTH ) IS result; + VARIABLE rv : integer; + BEGIN + IF r = 0 OR l'LENGTH = 0 THEN + RETURN l; + ELSIF r > 0 THEN + rv := r MOD l'length; + resultv(rv+1 TO l'LENGTH) := lv(1 TO l'LENGTH - rv); + resultv(1 TO rv) := lv(l'LENGTH - rv + 1 TO l'LENGTH); + RETURN result; + ELSE + RETURN l ROL (-r); + END IF; + END FUNCTION "ror"; + + ------------------------------------------------------------------- + -- vector/scalar overloaded logical operators + ------------------------------------------------------------------- + + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + FUNCTION "and" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "and" (lv(i), r); + END LOOP; + RETURN result; + END FUNCTION "and"; + ------------------------------------------------------------------- + FUNCTION "and" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "and" (lv(i), r); + END LOOP; + RETURN result; + END FUNCTION "and"; + ------------------------------------------------------------------- + FUNCTION "and" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "and" (l, rv(i)); + END LOOP; + RETURN result; + END FUNCTION "and"; + ------------------------------------------------------------------- + FUNCTION "and" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "and" (l, rv(i)); + END LOOP; + RETURN result; + END FUNCTION "and"; + + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + FUNCTION "nand" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("and" (lv(i), r)); + END LOOP; + RETURN result; + END FUNCTION "nand"; + ------------------------------------------------------------------- + FUNCTION "nand" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("and" (lv(i), r)); + END LOOP; + RETURN result; + END FUNCTION "nand"; + ------------------------------------------------------------------- + FUNCTION "nand" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("and" (l, rv(i))); + END LOOP; + RETURN result; + END FUNCTION "nand"; + ------------------------------------------------------------------- + FUNCTION "nand" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("and" (l, rv(i))); + END LOOP; + RETURN result; + END FUNCTION "nand"; + + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + FUNCTION "or" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "or" (lv(i), r); + END LOOP; + RETURN result; + END FUNCTION "or"; + ------------------------------------------------------------------- + FUNCTION "or" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "or" (lv(i), r); + END LOOP; + RETURN result; + END FUNCTION "or"; + ------------------------------------------------------------------- + FUNCTION "or" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "or" (l, rv(i)); + END LOOP; + RETURN result; + END FUNCTION "or"; + ------------------------------------------------------------------- + FUNCTION "or" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "or" (l, rv(i)); + END LOOP; + RETURN result; + END FUNCTION "or"; + + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + FUNCTION "nor" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("or" (lv(i), r)); + END LOOP; + RETURN result; + END FUNCTION "nor"; + ------------------------------------------------------------------- + FUNCTION "nor" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("or" (lv(i), r)); + END LOOP; + RETURN result; + END FUNCTION "nor"; + ------------------------------------------------------------------- + FUNCTION "nor" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("or" (l, rv(i))); + END LOOP; + RETURN result; + END FUNCTION "nor"; + ------------------------------------------------------------------- + FUNCTION "nor" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("or" (l, rv(i))); + END LOOP; + RETURN result; + END FUNCTION "nor"; + + ------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + FUNCTION "xor" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "xor" (lv(i), r); + END LOOP; + RETURN result; + END FUNCTION "xor"; + ------------------------------------------------------------------- + FUNCTION "xor" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "xor" (lv(i), r); + END LOOP; + RETURN result; + END FUNCTION "xor"; + ------------------------------------------------------------------- + FUNCTION "xor" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "xor" (l, rv(i)); + END LOOP; + RETURN result; + END FUNCTION "xor"; + ------------------------------------------------------------------- + FUNCTION "xor" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "xor" (l, rv(i)); + END LOOP; + RETURN result; + END FUNCTION "xor"; + + ------------------------------------------------------------------- + -- xnor + ------------------------------------------------------------------- + FUNCTION "xnor" ( l : std_logic_vector; r : std_ulogic ) RETURN std_logic_vector IS + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("xor" (lv(i), r)); + END LOOP; + RETURN result; + END FUNCTION "xnor"; + ------------------------------------------------------------------- + FUNCTION "xnor" ( l : std_ulogic_vector; r : std_ulogic ) RETURN std_ulogic_vector IS + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("xor" (lv(i), r)); + END LOOP; + RETURN result; + END FUNCTION "xnor"; + ------------------------------------------------------------------- + FUNCTION "xnor" ( l : std_ulogic; r : std_logic_vector ) RETURN std_logic_vector IS + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("xor" (l, rv(i))); + END LOOP; + RETURN result; + END FUNCTION "xnor"; + ------------------------------------------------------------------- + FUNCTION "xnor" ( l : std_ulogic; r : std_ulogic_vector ) RETURN std_ulogic_vector IS + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO r'LENGTH ); + BEGIN + FOR i IN result'RANGE LOOP + result(i) := "not"("xor" (l, rv(i))); + END LOOP; + RETURN result; + END FUNCTION "xnor"; + + ------------------------------------------------------------------- + -- vector-reduction functions + ------------------------------------------------------------------- + -- %%% Uncomment the new syntax functions below +-- ------------------------------------------------------------------- +-- -- and +-- ------------------------------------------------------------------- +-- FUNCTION and ( arg : std_logic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN and (to_StdULogicVector (arg)); +-- END FUNCTION and; +-- ------------------------------------------------------------------- +-- FUNCTION and ( arg : std_ulogic_vector ) RETURN std_ulogic IS +-- variable Upper, Lower : std_ulogic; +-- variable Half : integer; +-- variable BUS_int : std_ulogic_vector ( arg'length - 1 downto 0 ); +-- variable Result : std_ulogic := '1'; -- In the case of a NULL range +-- BEGIN +-- if (arg'LENGTH >= 1) then +-- BUS_int := to_ux01 (arg); +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := "and" (BUS_int(BUS_int'right),BUS_int(BUS_int'left)); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := and ( BUS_int ( BUS_int'left downto Half )); +-- Lower := and ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := "and" (Upper, Lower); +-- end if; +-- end if; +-- return Result; +-- END FUNCTION and; + +-- ------------------------------------------------------------------- +-- -- nand +-- ------------------------------------------------------------------- +-- FUNCTION nand ( arg : std_logic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN "not"(and(to_StdULogicVector(arg))); +-- END FUNCTION nand; +-- ------------------------------------------------------------------- +-- FUNCTION nand ( arg : std_ulogic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN "not"(and(arg)); +-- END FUNCTION nand; + +-- ------------------------------------------------------------------- +-- -- or +-- ------------------------------------------------------------------- +-- FUNCTION or ( arg : std_logic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN or (to_StdULogicVector (arg)); +-- END FUNCTION or; +-- ------------------------------------------------------------------- +-- FUNCTION or ( arg : std_ulogic_vector ) RETURN std_ulogic IS +-- variable Upper, Lower : std_ulogic; +-- variable Half : integer; +-- variable BUS_int : std_ulogic_vector ( arg'length - 1 downto 0 ); +-- variable Result : std_ulogic := '0'; -- In the case of a NULL range +-- BEGIN +-- if (arg'LENGTH >= 1) then +-- BUS_int := to_ux01 (arg); +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := "or" (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := or ( BUS_int ( BUS_int'left downto Half )); +-- Lower := or ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := "or" (Upper, Lower); +-- end if; +-- end if; +-- return Result; +-- END FUNCTION or; + +-- ------------------------------------------------------------------- +-- -- nor +-- ------------------------------------------------------------------- +-- FUNCTION nor ( arg : std_logic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN "not"(or(To_StdULogicVector(arg))); +-- END FUNCTION nor; +-- ------------------------------------------------------------------- +-- FUNCTION nor ( arg : std_ulogic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN "not"(or(arg)); +-- END FUNCTION nor; + +-- ------------------------------------------------------------------- +-- -- xor +-- ------------------------------------------------------------------- +-- FUNCTION xor ( arg : std_logic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN xor (to_StdULogicVector (arg)); +-- END FUNCTION xor; +-- ------------------------------------------------------------------- +-- FUNCTION xor ( arg : std_ulogic_vector ) RETURN std_ulogic IS +-- variable Upper, Lower : std_ulogic; +-- variable Half : integer; +-- variable BUS_int : std_ulogic_vector ( arg'length - 1 downto 0 ); +-- variable Result : std_ulogic := '0'; -- In the case of a NULL range +-- BEGIN +-- if (arg'LENGTH >= 1) then +-- BUS_int := to_ux01 (arg); +-- if ( BUS_int'length = 1 ) then +-- Result := BUS_int ( BUS_int'left ); +-- elsif ( BUS_int'length = 2 ) then +-- Result := "xor" (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); +-- else +-- Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; +-- Upper := xor ( BUS_int ( BUS_int'left downto Half )); +-- Lower := xor ( BUS_int ( Half - 1 downto BUS_int'right )); +-- Result := "xor" (Upper, Lower); +-- end if; +-- end if; +-- return Result; +-- END FUNCTION xor; + +-- ------------------------------------------------------------------- +-- -- xnor +-- ------------------------------------------------------------------- +-- FUNCTION xnor ( arg : std_logic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN "not"(xor(To_StdULogicVector(arg))); +-- END FUNCTION xnor; +-- ------------------------------------------------------------------- +-- FUNCTION xnor ( arg : std_ulogic_vector ) RETURN std_ulogic IS +-- BEGIN +-- RETURN "not"(xor(arg)); +-- END FUNCTION xnor; + ---------------------------------------------------------------------------- + -- %%% Remove the following funcitons (new syntax is above) + ---------------------------------------------------------------------------- + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + FUNCTION and_reduce ( arg : std_logic_vector ) RETURN std_ulogic IS + BEGIN + RETURN and_reduce (to_StdULogicVector (arg)); + END FUNCTION and_reduce; + ------------------------------------------------------------------- + FUNCTION and_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic IS + variable Upper, Lower : std_ulogic; + variable Half : integer; + variable BUS_int : std_ulogic_vector ( arg'length - 1 downto 0 ); + variable Result : std_ulogic := '1'; -- In the case of a NULL range + BEGIN + if (arg'LENGTH >= 1) then + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "and" (BUS_int(BUS_int'right),BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := and_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := and_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "and" (Upper, Lower); + end if; + end if; + return Result; + END FUNCTION and_reduce; + + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + FUNCTION nand_reduce ( arg : std_logic_vector ) RETURN std_ulogic IS + BEGIN + RETURN "not"(and_reduce(to_StdULogicVector(arg))); + END FUNCTION nand_reduce; + ------------------------------------------------------------------- + FUNCTION nand_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic IS + BEGIN + RETURN "not"(and_reduce(arg)); + END FUNCTION nand_reduce; + + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + FUNCTION or_reduce ( arg : std_logic_vector ) RETURN std_ulogic IS + BEGIN + RETURN or_reduce (to_StdULogicVector (arg)); + END FUNCTION or_reduce; + ------------------------------------------------------------------- + FUNCTION or_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic IS + variable Upper, Lower : std_ulogic; + variable Half : integer; + variable BUS_int : std_ulogic_vector ( arg'length - 1 downto 0 ); + variable Result : std_ulogic := '0'; -- In the case of a NULL range + BEGIN + if (arg'LENGTH >= 1) then + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "or" (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := or_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := or_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "or" (Upper, Lower); + end if; + end if; + return Result; + END FUNCTION or_reduce; + + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + FUNCTION nor_reduce ( arg : std_logic_vector ) RETURN std_ulogic IS + BEGIN + RETURN "not"(or_reduce(To_StdULogicVector(arg))); + END FUNCTION nor_reduce; + ------------------------------------------------------------------- + FUNCTION nor_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic IS + BEGIN + RETURN "not"(or_reduce(arg)); + END FUNCTION nor_reduce; + + ------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + FUNCTION xor_reduce ( arg : std_logic_vector ) RETURN std_ulogic IS + BEGIN + RETURN xor_reduce (to_StdULogicVector (arg)); + END FUNCTION xor_reduce; + ------------------------------------------------------------------- + FUNCTION xor_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic IS + variable Upper, Lower : std_ulogic; + variable Half : integer; + variable BUS_int : std_ulogic_vector ( arg'length - 1 downto 0 ); + variable Result : std_ulogic := '0'; -- In the case of a NULL range + BEGIN + if (arg'LENGTH >= 1) then + BUS_int := to_ux01 (arg); + if ( BUS_int'length = 1 ) then + Result := BUS_int ( BUS_int'left ); + elsif ( BUS_int'length = 2 ) then + Result := "xor" (BUS_int(BUS_int'right), BUS_int(BUS_int'left)); + else + Half := ( BUS_int'length + 1 ) / 2 + BUS_int'right; + Upper := xor_reduce ( BUS_int ( BUS_int'left downto Half )); + Lower := xor_reduce ( BUS_int ( Half - 1 downto BUS_int'right )); + Result := "xor" (Upper, Lower); + end if; + end if; + return Result; + END FUNCTION xor_reduce; + + ------------------------------------------------------------------- + -- xnor + ------------------------------------------------------------------- + FUNCTION xnor_reduce ( arg : std_logic_vector ) RETURN std_ulogic IS + BEGIN + RETURN "not"(xor_reduce(To_StdULogicVector(arg))); + END FUNCTION xnor_reduce; + ------------------------------------------------------------------- + FUNCTION xnor_reduce ( arg : std_ulogic_vector ) RETURN std_ulogic IS + BEGIN + RETURN "not"(xor_reduce(arg)); + END FUNCTION xnor_reduce; + -- %%% End "remove the following functions" + + -- Function from Proposal FT18 + function "and" (L: std_ulogic; R: boolean) return std_ulogic is + begin + if R then + return to_X01(L); + else + return '0'; + end if; + end function "and"; + function "and" (L: boolean; R: std_ulogic) return std_ulogic is + begin + if L then + return to_X01(R); + else + return '0'; + end if; + end function "and"; + function "or" (L: std_ulogic; R: boolean) return std_ulogic is + begin + if R then + return '1'; + else + return to_X01(L); + end if; + end function "or"; + function "or" (L: boolean; R: std_ulogic) return std_ulogic is + begin + if L then + return '1'; + else + return to_X01(R); + end if; + end function "or"; + function "xor" (L: std_ulogic; R: boolean) return std_ulogic is + begin + if R then + return not to_X01(L); + else + return to_X01(L); + end if; + end function "xor"; + function "xor" (L: boolean; R: std_ulogic) return std_ulogic is + begin + if L then + return not to_X01(R); + else + return to_X01(R); + end if; + end function "xor"; + function "nand" (L: std_ulogic; R: boolean) return std_ulogic is + begin + if R then + return not to_X01(L); + else + return '1'; + end if; + end function "nand"; + function "nand" (L: boolean; R: std_ulogic) return std_ulogic is + begin + if L then + return not to_X01(R); + else + return '1'; + end if; + end function "nand"; + function "nor" (L: std_ulogic; R: boolean) return std_ulogic is + begin + if R then + return '0'; + else + return not to_X01(L); + end if; + end function "nor"; + function "nor" (L: boolean; R: std_ulogic) return std_ulogic is + begin + if L then + return '0'; + else + return not to_X01(R); + end if; + end function "nor"; + function "xnor" (L: std_ulogic; R: boolean) return std_ulogic is + begin + if R then + return to_X01(L); + else + return not to_X01(L); + end if; + end function "xnor"; + function "xnor" (L: boolean; R: std_ulogic) return std_ulogic is + begin + if L then + return to_X01(R); + else + return not to_X01(R); + end if; + end function "xnor"; + + -- Used internally by the ?= operators + function find_msb ( + arg : STD_ULOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + alias xarg : STD_ULOGIC_VECTOR(arg'length-1 downto 0) is arg; + begin + for_loop : for i in xarg'range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_msb; + + function find_msb ( + arg : STD_LOGIC_VECTOR; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + begin + return find_msb (STD_ULOGIC_VECTOR (arg), y); + end function find_msb; + + -- The following functions are implicity in 1076-2006 + -- truth table for "?=" function + constant match_logic_table : stdlogic_table := ( + ----------------------------------------------------- + -- U X 0 1 Z W L H - | | + ----------------------------------------------------- + ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | + ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | + ); + + constant no_match_logic_table : stdlogic_table := ( + ----------------------------------------------------- + -- U X 0 1 Z W L H - | | + ----------------------------------------------------- + ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | + ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | + ); + + ------------------------------------------------------------------- + -- ?= functions, Similar to "std_match", but returns "std_ulogic". + ------------------------------------------------------------------- + -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS + function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin + return match_logic_table (l, r); + end function \?=\; + -- %%% END FUNCTION "?="; + ------------------------------------------------------------------- + -- %%% FUNCTION "?=" ( l, r : std_logic_vector ) RETURN std_ulogic IS + function \?=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; + variable result, result1 : STD_ULOGIC; -- result + begin + -- Logically identical to an "=" operator. + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?="": null detected, returning X" + severity warning; + return 'X'; + end if; + if lv'length /= rv'length then + report "STD_LOGIC_1164.""?="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + else + result := '1'; + for i in lv'low to lv'high loop + result1 := match_logic_table(lv(i), rv(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + -- %%% END FUNCTION "?="; + ------------------------------------------------------------------- + -- %%% FUNCTION "?=" ( l, r : std_ulogic_vector ) RETURN std_ulogic IS + function \?=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; + variable result, result1 : STD_ULOGIC; + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?="": null detected, returning X" + severity warning; + return 'X'; + end if; + if lv'length /= rv'length then + report "STD_LOGIC_1164.""?="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + else + result := '1'; + for i in lv'low to lv'high loop + result1 := match_logic_table(lv(i), rv(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; + -- %%% END FUNCTION "?="; + -- %%% FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin + return no_match_logic_table (l, r); + end function \?/=\; + -- %%% END FUNCTION "?/="; + -- %%% FUNCTION "?/=" ( l, r : std_logic_vector ) RETURN std_ulogic is + function \?/=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; + variable result, result1 : STD_ULOGIC; -- result + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?/="": null detected, returning X" + severity warning; + return 'X'; + end if; + if lv'length /= rv'length then + report "STD_LOGIC_1164.""?/="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + else + result := '0'; + for i in lv'low to lv'high loop + result1 := no_match_logic_table(lv(i), rv(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; + -- %%% END FUNCTION "?/="; + -- %%% FUNCTION "?/=" ( l, r : std_ulogic_vector ) RETURN std_ulogic is + function \?/=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; + variable result, result1 : STD_ULOGIC; + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?/="": null detected, returning X" + severity warning; + return 'X'; + end if; + if lv'length /= rv'length then + report "STD_LOGIC_1164.""?/="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + else + result := '0'; + for i in lv'low to lv'high loop + result1 := no_match_logic_table(lv(i), rv(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; + -- %%% END FUNCTION "?/="; + -- %%% FUNCTION "?>" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?>\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin + if (l = '-') or (r = '-') then + report "STD_LOGIC_1164.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01 (l); + rx := to_x01 (r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx > rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% END FUNCTION "?>"; + -- %%% FUNCTION "?>" ( l, r : std_logic_vector ) RETURN std_ulogic is + function \?>\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; + variable lx, rx : STD_LOGIC_VECTOR (l'range); + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?>"": null detected, returning X" + severity warning; + return 'X'; + elsif lv'length /= rv'length then + report "STD_LOGIC_1164.""?>"": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "STD_LOGIC_1164.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01(lv); + rx := to_x01(rv); + if is_x(lx) or is_x(rx) then + return 'X'; + elsif lx > rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% END FUNCTION "?/>"; + -- %%% FUNCTION "?>" ( l, r : std_ulogic_vector ) RETURN std_ulogic is + function \?>\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; + variable lx, rx : STD_ULOGIC_VECTOR (l'range); + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?>"": null detected, returning X" + severity warning; + return 'X'; + elsif lv'length /= rv'length then + report "STD_LOGIC_1164.""?>"": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "STD_LOGIC_1164.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01(lv); + rx := to_x01(rv); + if is_x(lx) or is_x(rx) then + return 'X'; + elsif lx > rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% END FUNCTION "?/>"; + -- %%% FUNCTION "?>=" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?>=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin + if (l = '-') or (r = '-') then + report "STD_LOGIC_1164.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01 (l); + rx := to_x01 (r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx >= rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% END FUNCTION "?/>="; + -- %%% FUNCTION "?>=" ( l, r : std_logic_vector ) RETURN std_ulogic is + function \?>=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; + variable lx, rx : STD_LOGIC_VECTOR (l'range); + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?>="": null detected, returning X" + severity warning; + return 'X'; + elsif lv'length /= rv'length then + report "STD_LOGIC_1164.""?>="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "STD_LOGIC_1164.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01(lv); + rx := to_x01(rv); + if is_x(lx) or is_x(rx) then + return 'X'; + elsif lx >= rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% END FUNCTION "?/>="; + -- %%% FUNCTION "?>=" ( l, r : std_ulogic_vector ) RETURN std_ulogic is + function \?>=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; + variable lx, rx : STD_ULOGIC_VECTOR (l'range); + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?>="": null detected, returning X" + severity warning; + return 'X'; + elsif lv'length /= rv'length then + report "STD_LOGIC_1164.""?>="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "STD_LOGIC_1164.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01(lv); + rx := to_x01(rv); + if is_x(lx) or is_x(rx) then + return 'X'; + elsif lx >= rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% END FUNCTION "?/>="; + -- %%% FUNCTION "?<" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?<\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin + if (l = '-') or (r = '-') then + report "STD_LOGIC_1164.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01 (l); + rx := to_x01 (r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx < rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% END FUNCTION "?/<"; + -- %%% FUNCTION "?<" ( l, r : std_logic_vector ) RETURN std_ulogic is + function \?<\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; + variable lx, rx : STD_LOGIC_VECTOR (l'range); + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?<"": null detected, returning X" + severity warning; + return 'X'; + elsif lv'length /= rv'length then + report "STD_LOGIC_1164.""?<"": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "STD_LOGIC_1164.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01(lv); + rx := to_x01(rv); + if is_x(lx) or is_x(rx) then + return 'X'; + elsif lx < rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% END FUNCTION "?/<"; + -- %%% FUNCTION "?<" ( l, r : std_ulogic_vector ) RETURN std_ulogic is + function \?<\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; + variable lx, rx : STD_ULOGIC_VECTOR (l'range); + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?<"": null detected, returning X" + severity warning; + return 'X'; + elsif lv'length /= rv'length then + report "STD_LOGIC_1164.""?<"": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "STD_LOGIC_1164.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01(lv); + rx := to_x01(rv); + if is_x(lx) or is_x(rx) then + return 'X'; + elsif lx < rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% END FUNCTION "?/<"; + -- %%% FUNCTION "?<=" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?<=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + variable lx, rx : STD_ULOGIC; + begin + if (l = '-') or (r = '-') then + report "STD_LOGIC_1164.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01 (l); + rx := to_x01 (r); + if lx = 'X' or rx = 'X' then + return 'X'; + elsif lx <= rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% END FUNCTION "?/<="; + -- %%% FUNCTION "?<=" ( l, r : std_logic_vector ) RETURN std_ulogic is + function \?<=\ (l, r : STD_LOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_LOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_LOGIC_VECTOR(1 to r'length) is r; + variable lx, rx : STD_LOGIC_VECTOR (l'range); + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?<="": null detected, returning X" + severity warning; + return 'X'; + elsif lv'length /= rv'length then + report "STD_LOGIC_1164.""?<="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "STD_LOGIC_1164.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01(lv); + rx := to_x01(rv); + if is_x(lx) or is_x(rx) then + return 'X'; + elsif lx <= rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% END FUNCTION "?/<="; + -- %%% FUNCTION "?<=" ( l, r : std_ulogic_vector ) RETURN std_ulogic is + function \?<=\ (l, r : STD_ULOGIC_VECTOR) return STD_ULOGIC is + alias lv : STD_ULOGIC_VECTOR(1 to l'length) is l; + alias rv : STD_ULOGIC_VECTOR(1 to r'length) is r; + variable lx, rx : STD_ULOGIC_VECTOR (l'range); + begin + if ((l'length < 1) or (r'length < 1)) then + report "STD_LOGIC_1164.""?<="": null detected, returning X" + severity warning; + return 'X'; + elsif lv'length /= rv'length then + report "STD_LOGIC_1164.""?<="": L'LENGTH /= R'LENGTH, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= -1) or (find_msb (r, '-') /= -1) then + report "STD_LOGIC_1164.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + lx := to_x01(lv); + rx := to_x01(rv); + if is_x(lx) or is_x(rx) then + return 'X'; + elsif lx <= rx then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% END FUNCTION "?/<="; + + -- "??" operator, converts a std_ulogic to a boolean. +-- %%% FUNCTION "??" + function \??\ (S : STD_ULOGIC) return BOOLEAN is + begin + return S = '1' or S = 'H'; + end function \??\; +-- %%% END FUNCTION "??"; + + -- rtl_synthesis off + ----------------------------------------------------------------------------- + -- This section copied from "std_logic_textio" + ----------------------------------------------------------------------------- + -- Type and constant definitions used to map STD_ULOGIC values + -- into/from character values. + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', ERROR); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of character; + type MVL9_indexed_by_char is array (character) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (character) of MVL9plus; + constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9 : MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus : MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => ERROR); + + constant NBSP : character := character'val(160); -- space character + constant NUS : string(2 to 1) := (others => ' '); -- null string + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC; + GOOD : out BOOLEAN) is + variable c : character; + variable readOk : BOOLEAN; + begin + VALUE := 'U'; -- initialize to a "U" + loop -- skip white space + read(l, c, readOk); -- but also exit on a bad read + exit when (readOk = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if not readOk then + good := FALSE; + else + if char_to_MVL9plus(c) = ERROR then + good := FALSE; + else + VALUE := char_to_MVL9(c); + good := TRUE; + end if; + end if; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable m : STD_ULOGIC; + variable c : character; + variable s : string(1 to VALUE'length-1); + variable mv : STD_ULOGIC_VECTOR(0 to VALUE'length-1); + variable readOk : BOOLEAN; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, readOk); + exit when (readOk = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not readOk then + good := FALSE; + return; + end if; + if char_to_MVL9plus(c) = ERROR then + good := FALSE; + return; + end if; + read(L, s, readOk); + -- Bail out if there was a bad read + if not readOk then + good := FALSE; + return; + end if; + for i in 1 to VALUE'length-1 loop + if char_to_MVL9plus(s(i)) = ERROR then + good := FALSE; + return; + end if; + end loop; + mv(0) := char_to_MVL9(c); + for i in 1 to VALUE'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + VALUE := mv; + good := TRUE; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC) is + variable c : character; + variable readOk : BOOLEAN; + begin + VALUE := 'U'; -- initialize to a "U" + loop -- skip white space + read(l, c, readOk); + exit when (readOk = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if not readOk then + report "STD_LOGIC_1164.READ(STD_ULOGIC) " + & "Error end of string encountered" + severity error; + return; + elsif char_to_MVL9plus(c) = ERROR then + report + "STD_LOGIC_1164.READ(STD_ULOGIC) Error: Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + else + VALUE := char_to_MVL9(c); + end if; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable m : STD_ULOGIC; + variable c : character; + variable readOk : BOOLEAN; + variable s : string(1 to VALUE'length-1); + variable mv : STD_ULOGIC_VECTOR(0 to VALUE'length-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, readOk); + exit when (readOk = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if readOk = false then -- Bail out if there was a bad read + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Error end of string encountered" + severity error; + return; + elsif char_to_MVL9plus(c) = ERROR then + report + "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) Error: Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + end if; + read(L, s, readOk); + if readOk then + for i in 1 to VALUE'length-1 loop + if char_to_MVL9plus(s(i)) = ERROR then + report + "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) Error: Character '" & + s(i) & "' read, expected STD_ULOGIC literal." + severity error; + return; + end if; + end loop; + else + report "STD_LOGIC_1164.READ(STD_ULOGIC_VECTOR) " + & "Error end of string encountered" + severity error; + return; + end if; + mv(0) := char_to_MVL9(c); + for i in 1 to VALUE'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + VALUE := mv; + end procedure READ; + + procedure WRITE (L : inout LINE; VALUE : in STD_ULOGIC; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) is + begin + write(l, MVL9_to_char(VALUE), justified, field); + end procedure WRITE; + + procedure WRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) is + variable s : string(1 to VALUE'length); + variable m : STD_ULOGIC_VECTOR(1 to VALUE'length) := VALUE; + begin + for i in 1 to VALUE'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(l, s, justified, field); + end procedure WRITE; + + -- Read and Write procedures for STD_LOGIC_VECTOR + + procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable m : STD_LOGIC; + variable c : character; + variable s : string(1 to VALUE'length-1); + variable mv : STD_LOGIC_VECTOR(0 to VALUE'length-1); + variable readOk : BOOLEAN; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, readOk); + exit when (readOk = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not readOk then + good := FALSE; + return; + end if; + if char_to_MVL9plus(c) = ERROR then + good := FALSE; + return; + end if; + read(L, s, readOk); + -- Bail out if there was a bad read + if not readOk then + good := FALSE; + return; + end if; + for i in 1 to VALUE'length-1 loop + if char_to_MVL9plus(s(i)) = ERROR then + good := FALSE; + return; + end if; + end loop; + mv(0) := char_to_MVL9(c); + for i in 1 to VALUE'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + VALUE := mv; + good := TRUE; + end procedure READ; + + procedure READ (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is + variable m : STD_LOGIC; + variable c : character; + variable readOk : BOOLEAN; + variable s : string(1 to VALUE'length-1); + variable mv : STD_LOGIC_VECTOR(0 to VALUE'length-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, readOk); + exit when (readOk = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if readOk = false then -- Bail out if there was a bad read + report "STD_LOGIC_1164.READ(STD_LOGIC_VECTOR) " + & "Error end of string encountered" + severity error; + return; + elsif char_to_MVL9plus(c) = ERROR then + report + "STD_LOGIC_1164.READ(STD_LOGIC_VECTOR) Error: Character '" & + c & "' read, expected STD_ULOGIC literal." + severity error; + return; + end if; + read(L, s, readOk); + if readOk then + for i in 1 to VALUE'length-1 loop + if (char_to_MVL9plus(s(i)) = ERROR) then + report + "STD_LOGIC_1164.READ(STD_LOGIC_VECTOR) Error: Character '" & + s(i) & "' read, expected STD_ULOGIC literal." + severity error; + return; + end if; + end loop; + else + report "STD_LOGIC_1164.READ(STD_LOGIC_VECTOR) " + & "Error end of string encountered" + severity error; + return; + end if; + mv(0) := char_to_MVL9(c); + for i in 1 to VALUE'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + VALUE := mv; + end procedure READ; + + procedure WRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) is + variable s : string(1 to VALUE'length); + variable m : STD_LOGIC_VECTOR(1 to VALUE'length) := VALUE; + begin + for i in 1 to VALUE'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(L, s, justified, field); + end procedure WRITE; + + ----------------------------------------------------------------------- + -- Alias for bread and bwrite are provided with call out the read and + -- write functions. + ----------------------------------------------------------------------- + + -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2QuadBits (C : Character; + RESULT : out std_ulogic_vector(3 downto 0); + GOOD : out Boolean; + ISSUE_ERROR : in Boolean) is + begin + case c is + when '0' => result := x"0"; good := TRUE; + when '1' => result := x"1"; good := TRUE; + when '2' => result := x"2"; good := TRUE; + when '3' => result := x"3"; good := TRUE; + when '4' => result := x"4"; good := TRUE; + when '5' => result := x"5"; good := TRUE; + when '6' => result := x"6"; good := TRUE; + when '7' => result := x"7"; good := TRUE; + when '8' => result := x"8"; good := TRUE; + when '9' => result := x"9"; good := TRUE; + when 'A' | 'a' => result := x"A"; good := TRUE; + when 'B' | 'b' => result := x"B"; good := TRUE; + when 'C' | 'c' => result := x"C"; good := TRUE; + when 'D' | 'd' => result := x"D"; good := TRUE; + when 'E' | 'e' => result := x"E"; good := TRUE; + when 'F' | 'f' => result := x"F"; good := TRUE; + when 'Z' => result := "ZZZZ"; good := TRUE; + when 'X' => result := "XXXX"; good := TRUE; + when others => + assert not ISSUE_ERROR + report + "STD_LOGIC_1164.HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)." + severity error; + good := FALSE; + end case; + end procedure Char2QuadBits; + + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : std_ulogic_vector(0 to ne*4 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + good := FALSE; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + VALUE := sv (pad to sv'high); + end if; + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : std_ulogic_vector(0 to ne*4 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.HREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, TRUE); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "STD_LOGIC_1164.HREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, TRUE); + if not ok then + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.HREAD Error: Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end procedure HREAD; + + procedure HWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) is + begin + write (L, to_hstring (VALUE), JUSTIFIED, FIELD); + end procedure HWRITE; + + + -- Octal Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2TriBits (C : Character; + RESULT : out std_ulogic_vector(2 downto 0); + GOOD : out Boolean; + ISSUE_ERROR : in Boolean) is + begin + case c is + when '0' => result := o"0"; good := TRUE; + when '1' => result := o"1"; good := TRUE; + when '2' => result := o"2"; good := TRUE; + when '3' => result := o"3"; good := TRUE; + when '4' => result := o"4"; good := TRUE; + when '5' => result := o"5"; good := TRUE; + when '6' => result := o"6"; good := TRUE; + when '7' => result := o"7"; good := TRUE; + when 'Z' => result := "ZZZ"; good := TRUE; + when 'X' => result := "XXX"; good := TRUE; + when others => + assert not ISSUE_ERROR + report + "STD_LOGIC_1164.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + good := FALSE; + end case; + end procedure Char2TriBits; + + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : std_ulogic_vector(0 to ne*3 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + good := FALSE; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + VALUE := sv (pad to sv'high); + end if; + end procedure OREAD; + + procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) is + variable c : character; + variable ok : boolean; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : std_ulogic_vector(0 to ne*3 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.OREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, TRUE); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "STD_LOGIC_1164.OREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, TRUE); + if not ok then + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.OREAD Error: Vector truncated" + severity error; + else + VALUE := sv (pad to sv'high); + end if; + end procedure OREAD; + + procedure OWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) is + begin + write (L, to_ostring(VALUE), JUSTIFIED, FIELD); + end procedure OWRITE; + + -- Hex Read and Write procedures for STD_LOGIC_VECTOR + + procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : std_ulogic_vector(0 to ne*4 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(l, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + good := FALSE; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + VALUE := to_stdlogicvector(sv (pad to sv'high)); + good := true; + end if; + end procedure HREAD; + + procedure HREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (VALUE'length+3)/4; + constant pad : INTEGER := ne*4 - VALUE'length; + variable sv : std_ulogic_vector(0 to ne*4 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(l, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.HREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2QuadBits(c, sv(0 to 3), ok, TRUE); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "STD_LOGIC_1164.HREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2QuadBits(s(i), sv(4*i to 4*i+3), ok, TRUE); + if not ok then + return; + end if; + end loop; + VALUE := to_stdlogicvector(sv (pad to sv'high)); + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.HREAD Error: Vector truncated" + severity error; + end if; + end procedure HREAD; + + procedure HWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) is + begin + write (L, to_hstring(VALUE), JUSTIFIED, FIELD); + end procedure HWRITE; + + -- Octal Read and Write procedures for STD_LOGIC_VECTOR + + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; + GOOD : out BOOLEAN) is + variable ok : boolean; + variable c : character; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : std_ulogic_vector(0 to ne*3 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + good := FALSE; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + VALUE := to_stdlogicvector (sv (pad to sv'high)); + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + good := false; -- vector was truncated. + else + good := true; + end if; + end procedure OREAD; + + procedure OREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) is + variable c : character; + variable ok : boolean; + constant ne : INTEGER := (VALUE'length+2)/3; + constant pad : INTEGER := ne*3 - VALUE'length; + variable sv : std_ulogic_vector(0 to ne*3 - 1); + variable s : string(1 to ne-1); + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, ok); + exit when (ok = FALSE) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + -- Bail out if there was a bad read + if not ok then + report "STD_LOGIC_1164.OREAD Error: Failed skipping white space" + severity error; + return; + end if; + Char2TriBits(c, sv(0 to 2), ok, TRUE); + if not ok then + return; + end if; + read(L, s, ok); + if not ok then + report "STD_LOGIC_1164.OREAD Error: Failed to read the STRING" + severity error; + return; + end if; + for i in 1 to ne-1 loop + Char2TriBits(s(i), sv(3*i to 3*i+2), ok, TRUE); + if not ok then + return; + end if; + end loop; + VALUE := to_stdlogicvector (sv (pad to sv'high)); + if or_reduce (sv (0 to pad-1)) = '1' then -- %%% replace with "or" + report "STD_LOGIC_1164.OREAD Error: Vector truncated" + severity error; + end if; + end procedure OREAD; + + procedure OWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) is + begin + write (L, to_ostring(VALUE), JUSTIFIED, FIELD); + end procedure OWRITE; + + ----------------------------------------------------------------------------- + -- New string functions for vhdl-200x fast track + ----------------------------------------------------------------------------- + + function justify ( + value : STRING; + justified : SIDE := right; + field : width := 0) + return STRING is + constant VAL_LEN : INTEGER := value'length; + variable result : STRING (1 to field) := (others => ' '); + begin -- function justify + -- return value if field is too small + if VAL_LEN >= field then + return value; + end if; + if justified = left then + result(1 to VAL_LEN) := value; + elsif justified = right then + result(field - VAL_LEN + 1 to field) := value; + end if; + return result; + end function justify; + + ----------------------------------------------------------------------------- + -- New string functions for vhdl-200x fast track + ----------------------------------------------------------------------------- + function to_string ( + value : in STD_ULOGIC; + justified : in side := RIGHT; + field : in width := 0 + ) return STRING is + variable result : STRING (1 to 1); + begin + result (1) := MVL9_to_char (value); + return justify (result, justified, field); + end function to_string; + ------------------------------------------------------------------- + -- TO_STRING (an alias called "to_bstring" is provide) + ------------------------------------------------------------------- + function to_string ( + value : in std_ulogic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + alias ivalue : std_ulogic_vector(1 to value'length) is value; + variable result : string(1 to value'length); + begin + if value'length < 1 then + return NUS; + else + for i in ivalue'range loop + result(i) := MVL9_to_char( iValue(i) ); + end loop; + return justify(result, justified, field); + end if; + end function to_string; + + ------------------------------------------------------------------- + -- TO_HSTRING + ------------------------------------------------------------------- + function to_hstring ( + value : in std_ulogic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + constant ne : integer := (value'length+3)/4; + variable pad : std_ulogic_vector(0 to (ne*4 - value'length) - 1); + variable ivalue : std_ulogic_vector(0 to ne*4 - 1); + variable result : string(1 to ne); + variable quad : std_ulogic_vector(0 to 3); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + quad := To_X01Z(ivalue(4*i to 4*i+3)); + case quad is + when x"0" => result(i+1) := '0'; + when x"1" => result(i+1) := '1'; + when x"2" => result(i+1) := '2'; + when x"3" => result(i+1) := '3'; + when x"4" => result(i+1) := '4'; + when x"5" => result(i+1) := '5'; + when x"6" => result(i+1) := '6'; + when x"7" => result(i+1) := '7'; + when x"8" => result(i+1) := '8'; + when x"9" => result(i+1) := '9'; + when x"A" => result(i+1) := 'A'; + when x"B" => result(i+1) := 'B'; + when x"C" => result(i+1) := 'C'; + when x"D" => result(i+1) := 'D'; + when x"E" => result(i+1) := 'E'; + when x"F" => result(i+1) := 'F'; + when "ZZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_hstring; + + ------------------------------------------------------------------- + -- TO_OSTRING + ------------------------------------------------------------------- + function to_ostring ( + value : in std_ulogic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + constant ne : integer := (value'length+2)/3; + variable pad : std_ulogic_vector(0 to (ne*3 - value'length) - 1); + variable ivalue : std_ulogic_vector(0 to ne*3 - 1); + variable result : string(1 to ne); + variable tri : std_ulogic_vector(0 to 2); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + tri := To_X01Z(ivalue(3*i to 3*i+2)); + case tri is + when o"0" => result(i+1) := '0'; + when o"1" => result(i+1) := '1'; + when o"2" => result(i+1) := '2'; + when o"3" => result(i+1) := '3'; + when o"4" => result(i+1) := '4'; + when o"5" => result(i+1) := '5'; + when o"6" => result(i+1) := '6'; + when o"7" => result(i+1) := '7'; + when "ZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_ostring; + + function to_string ( + value : in std_logic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + begin + return to_string (to_stdulogicvector (value), justified, field); + end function to_string; + + function to_hstring ( + value : in std_logic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + begin + return to_hstring (to_stdulogicvector (value), justified, field); + end function to_hstring; + + function to_ostring ( + value : in std_logic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return string is + begin + return to_ostring (to_stdulogicvector (value), justified, field); + end function to_ostring; + + ----------------------------------------------------------------------- + -- Alias for bread and bwrite are provided with call out the read and + -- write functions. + ----------------------------------------------------------------------- + function to_bstring ( + value : in std_ulogic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return STRING is + begin + return to_string (value, justified, field); + end function to_bstring; + + function to_bstring ( + value : in std_logic_vector; + justified : in side := RIGHT; + field : in width := 0 + ) return STRING is + begin + return to_string (value, justified, field); + end function to_bstring; + + procedure BREAD (L : inout LINE; VALUE : out STD_ULOGIC; GOOD : out BOOLEAN) + is + begin + READ (L, VALUE, GOOD); + end procedure BREAD; + procedure BREAD (L : inout LINE; VALUE : out STD_ULOGIC) + is + begin + READ (L, VALUE); + end procedure BREAD; + + procedure BREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN) + is + begin + READ (L, VALUE, GOOD); + end procedure BREAD; + procedure BREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR) + is + begin + READ (L, VALUE); + end procedure BREAD; + procedure BREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR; GOOD : out BOOLEAN) + is + begin + READ (L, VALUE, GOOD); + end procedure BREAD; + procedure BREAD (L : inout LINE; VALUE : out STD_LOGIC_VECTOR) + is + begin + READ (L, VALUE); + end procedure BREAD; + procedure BWRITE (L : inout LINE; VALUE : in STD_ULOGIC; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) + is + begin + WRITE (L, VALUE, JUSTIFIED, FIELD); + end procedure BWRITE; + + procedure BWRITE (L : inout LINE; VALUE : in STD_ULOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) + is + begin + WRITE (L, VALUE, JUSTIFIED, FIELD); + end procedure BWRITE; + procedure BWRITE (L : inout LINE; VALUE : in STD_LOGIC_VECTOR; + JUSTIFIED : in SIDE := RIGHT; FIELD : in WIDTH := 0) + is + begin + WRITE (L, VALUE, JUSTIFIED, FIELD); + end procedure BWRITE; + -- rtl_synthesis on +end package body std_logic_1164_additions; diff --git a/lib/Standard/ieee/math_complex.vhd b/lib/Standard/ieee/math_complex.vhd new file mode 100644 index 0000000..278f741 --- /dev/null +++ b/lib/Standard/ieee/math_complex.vhd @@ -0,0 +1,1087 @@ +------------------------------------------------------------------------ +-- +-- Copyright 1996 by IEEE. All rights reserved. +-- +-- This source file is an essential part of IEEE Std 1076.2-1996, IEEE Standard +-- VHDL Mathematical Packages. This source file may not be copied, sold, or +-- included with software that is sold without written permission from the IEEE +-- Standards Department. This source file may be used to implement this standard +-- and may be distributed in compiled form in any manner so long as the +-- compiled form does not allow direct decompilation of the original source file. +-- This source file may be copied for individual use between licensed users. +-- This source file is provided on an AS IS basis. The IEEE disclaims ANY +-- WARRANTY EXPRESS OR IMPLIED INCLUDING ANY WARRANTY OF MERCHANTABILITY +-- AND FITNESS FOR USE FOR A PARTICULAR PURPOSE. The user of the source +-- file shall indemnify and hold IEEE harmless from any damages or liability +-- arising out of the use thereof. +-- +-- Title: Standard VHDL Mathematical Packages (IEEE Std 1076.2-1996, +-- MATH_COMPLEX) +-- +-- Library: This package shall be compiled into a library +-- symbolically named IEEE. +-- +-- Developers: IEEE DASC VHDL Mathematical Packages Working Group +-- +-- Purpose: This package defines a standard for designers to use in +-- describing VHDL models that make use of common COMPLEX +-- constants and common COMPLEX mathematical functions and +-- operators. +-- +-- Limitation: The values generated by the functions in this package may +-- vary from platform to platform, and the precision of results +-- is only guaranteed to be the minimum required by IEEE Std 1076- +-- 1993. +-- +-- Notes: +-- No declarations or definitions shall be included in, or +-- excluded from, this package. +-- The "package declaration" defines the types, subtypes, and +-- declarations of MATH_COMPLEX. +-- The standard mathematical definition and conventional meaning +-- of the mathematical functions that are part of this standard +-- represent the formal semantics of the implementation of the +-- MATH_COMPLEX package declaration. The purpose of the +-- MATH_COMPLEX package body is to provide a guideline for +-- implementations to verify their implementation of MATH_COMPLEX. +-- Tool developers may choose to implement the package body in +-- the most efficient manner available to them. +-- +-- ----------------------------------------------------------------------------- +-- Version : 1.5 +-- Date : 24 July 1996 +-- ----------------------------------------------------------------------------- + +use WORK.MATH_REAL.all; +package MATH_COMPLEX is + constant CopyRightNotice: STRING + := "Copyright 1996 IEEE. All rights reserved."; + + -- + -- Type Definitions + -- + type COMPLEX is + record + RE: REAL; -- Real part + IM: REAL; -- Imaginary part + end record; + + subtype POSITIVE_REAL is REAL range 0.0 to REAL'HIGH; + + subtype PRINCIPAL_VALUE is REAL range -MATH_PI to MATH_PI; + + type COMPLEX_POLAR is + record + MAG: POSITIVE_REAL; -- Magnitude + ARG: PRINCIPAL_VALUE; -- Angle in radians; -MATH_PI is illegal + end record; + + -- + -- Constant Definitions + -- + constant MATH_CBASE_1: COMPLEX := COMPLEX'(1.0, 0.0); + constant MATH_CBASE_J: COMPLEX := COMPLEX'(0.0, 1.0); + constant MATH_CZERO: COMPLEX := COMPLEX'(0.0, 0.0); + + + -- + -- Overloaded equality and inequality operators for COMPLEX_POLAR + -- (equality and inequality operators for COMPLEX are predefined) + -- + + function "=" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR ) return BOOLEAN; + -- Purpose: + -- Returns TRUE if L is equal to R and returns FALSE otherwise + -- Special values: + -- COMPLEX_POLAR'(0.0, X) = COMPLEX_POLAR'(0.0, Y) returns TRUE + -- regardless of the value of X and Y. + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Error if R.ARG = -MATH_PI + -- Range: + -- "="(L,R) is either TRUE or FALSE + -- Notes: + -- None + + function "/=" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR ) return BOOLEAN; + -- Purpose: + -- Returns TRUE if L is not equal to R and returns FALSE + -- otherwise + -- Special values: + -- COMPLEX_POLAR'(0.0, X) /= COMPLEX_POLAR'(0.0, Y) returns + -- FALSE regardless of the value of X and Y. + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Error if R.ARG = -MATH_PI + -- Range: + -- "/="(L,R) is either TRUE or FALSE + -- Notes: + -- None + + -- + -- Function Declarations + -- + function CMPLX(X: in REAL; Y: in REAL:= 0.0 ) return COMPLEX; + -- Purpose: + -- Returns COMPLEX number X + iY + -- Special values: + -- None + -- Domain: + -- X in REAL + -- Y in REAL + -- Error conditions: + -- None + -- Range: + -- CMPLX(X,Y) is mathematically unbounded + -- Notes: + -- None + + function GET_PRINCIPAL_VALUE(X: in REAL ) return PRINCIPAL_VALUE; + -- Purpose: + -- Returns principal value of angle X; X in radians + -- Special values: + -- None + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- -MATH_PI < GET_PRINCIPAL_VALUE(X) <= MATH_PI + -- Notes: + -- None + + function COMPLEX_TO_POLAR(Z: in COMPLEX ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value COMPLEX_POLAR of Z + -- Special values: + -- COMPLEX_TO_POLAR(MATH_CZERO) = COMPLEX_POLAR'(0.0, 0.0) + -- COMPLEX_TO_POLAR(Z) = COMPLEX_POLAR'(ABS(Z.IM), + -- SIGN(Z.IM)*MATH_PI_OVER_2) if Z.RE = 0.0 + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function POLAR_TO_COMPLEX(Z: in COMPLEX_POLAR ) return COMPLEX; + -- Purpose: + -- Returns COMPLEX value of Z + -- Special values: + -- None + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- POLAR_TO_COMPLEX(Z) is mathematically unbounded + -- Notes: + -- None + + function "ABS"(Z: in COMPLEX ) return POSITIVE_REAL; + -- Purpose: + -- Returns absolute value (magnitude) of Z + -- Special values: + -- None + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- ABS(Z) is mathematically unbounded + -- Notes: + -- ABS(Z) = SQRT(Z.RE*Z.RE + Z.IM*Z.IM) + + function "ABS"(Z: in COMPLEX_POLAR ) return POSITIVE_REAL; + -- Purpose: + -- Returns absolute value (magnitude) of Z + -- Special values: + -- None + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- ABS(Z) >= 0.0 + -- Notes: + -- ABS(Z) = Z.MAG + + function ARG(Z: in COMPLEX ) return PRINCIPAL_VALUE; + -- Purpose: + -- Returns argument (angle) in radians of the principal + -- value of Z + -- Special values: + -- ARG(Z) = 0.0 if Z.RE >= 0.0 and Z.IM = 0.0 + -- ARG(Z) = SIGN(Z.IM)*MATH_PI_OVER_2 if Z.RE = 0.0 + -- ARG(Z) = MATH_PI if Z.RE < 0.0 and Z.IM = 0.0 + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- -MATH_PI < ARG(Z) <= MATH_PI + -- Notes: + -- ARG(Z) = ARCTAN(Z.IM, Z.RE) + + function ARG(Z: in COMPLEX_POLAR ) return PRINCIPAL_VALUE; + -- Purpose: + -- Returns argument (angle) in radians of the principal + -- value of Z + -- Special values: + -- None + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- -MATH_PI < ARG(Z) <= MATH_PI + -- Notes: + -- ARG(Z) = Z.ARG + + + function "-" (Z: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns unary minus of Z + -- Special values: + -- None + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- "-"(Z) is mathematically unbounded + -- Notes: + -- Returns -x -jy for Z= x + jy + + function "-" (Z: in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of unary minus of Z + -- Special values: + -- "-"(Z) = COMPLEX_POLAR'(Z.MAG, MATH_PI) if Z.ARG = 0.0 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- Returns COMPLEX_POLAR'(Z.MAG, Z.ARG - SIGN(Z.ARG)*MATH_PI) if + -- Z.ARG /= 0.0 + + function CONJ (Z: in COMPLEX) return COMPLEX; + -- Purpose: + -- Returns complex conjugate of Z + -- Special values: + -- None + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- CONJ(Z) is mathematically unbounded + -- Notes: + -- Returns x -jy for Z= x + jy + + function CONJ (Z: in COMPLEX_POLAR) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of complex conjugate of Z + -- Special values: + -- CONJ(Z) = COMPLEX_POLAR'(Z.MAG, MATH_PI) if Z.ARG = MATH_PI + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- Returns COMPLEX_POLAR'(Z.MAG, -Z.ARG) if Z.ARG /= MATH_PI + + function SQRT(Z: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns square root of Z with positive real part + -- or, if the real part is zero, the one with nonnegative + -- imaginary part + -- Special values: + -- SQRT(MATH_CZERO) = MATH_CZERO + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- SQRT(Z) is mathematically unbounded + -- Notes: + -- None + + function SQRT(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns square root of Z with positive real part + -- or, if the real part is zero, the one with nonnegative + -- imaginary part + -- Special values: + -- SQRT(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = 0.0 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function EXP(Z: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns exponential of Z + -- Special values: + -- EXP(MATH_CZERO) = MATH_CBASE_1 + -- EXP(Z) = -MATH_CBASE_1 if Z.RE = 0.0 and ABS(Z.IM) = MATH_PI + -- EXP(Z) = SIGN(Z.IM)*MATH_CBASE_J if Z.RE = 0.0 and + -- ABS(Z.IM) = MATH_PI_OVER_2 + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- EXP(Z) is mathematically unbounded + -- Notes: + -- None + + + + function EXP(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of exponential of Z + -- Special values: + -- EXP(Z) = COMPLEX_POLAR'(1.0, 0.0) if Z.MAG =0.0 and + -- Z.ARG = 0.0 + -- EXP(Z) = COMPLEX_POLAR'(1.0, MATH_PI) if Z.MAG = MATH_PI and + -- ABS(Z.ARG) = MATH_PI_OVER_2 + -- EXP(Z) = COMPLEX_POLAR'(1.0, MATH_PI_OVER_2) if + -- Z.MAG = MATH_PI_OVER_2 and + -- Z.ARG = MATH_PI_OVER_2 + -- EXP(Z) = COMPLEX_POLAR'(1.0, -MATH_PI_OVER_2) if + -- Z.MAG = MATH_PI_OVER_2 and + -- Z.ARG = -MATH_PI_OVER_2 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function LOG(Z: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns natural logarithm of Z + -- Special values: + -- LOG(MATH_CBASE_1) = MATH_CZERO + -- LOG(-MATH_CBASE_1) = COMPLEX'(0.0, MATH_PI) + -- LOG(MATH_CBASE_J) = COMPLEX'(0.0, MATH_PI_OVER_2) + -- LOG(-MATH_CBASE_J) = COMPLEX'(0.0, -MATH_PI_OVER_2) + -- LOG(Z) = MATH_CBASE_1 if Z = COMPLEX'(MATH_E, 0.0) + -- Domain: + -- Z in COMPLEX and ABS(Z) /= 0.0 + -- Error conditions: + -- Error if ABS(Z) = 0.0 + -- Range: + -- LOG(Z) is mathematically unbounded + -- Notes: + -- None + + function LOG2(Z: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns logarithm base 2 of Z + -- Special values: + -- LOG2(MATH_CBASE_1) = MATH_CZERO + -- LOG2(Z) = MATH_CBASE_1 if Z = COMPLEX'(2.0, 0.0) + -- Domain: + -- Z in COMPLEX and ABS(Z) /= 0.0 + -- Error conditions: + -- Error if ABS(Z) = 0.0 + -- Range: + -- LOG2(Z) is mathematically unbounded + -- Notes: + -- None + + function LOG10(Z: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns logarithm base 10 of Z + -- Special values: + -- LOG10(MATH_CBASE_1) = MATH_CZERO + -- LOG10(Z) = MATH_CBASE_1 if Z = COMPLEX'(10.0, 0.0) + -- Domain: + -- Z in COMPLEX and ABS(Z) /= 0.0 + -- Error conditions: + -- Error if ABS(Z) = 0.0 + -- Range: + -- LOG10(Z) is mathematically unbounded + -- Notes: + -- None + + function LOG(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of natural logarithm of Z + -- Special values: + -- LOG(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = 1.0 and + -- Z.ARG = 0.0 + -- LOG(Z) = COMPLEX_POLAR'(MATH_PI, MATH_PI_OVER_2) if + -- Z.MAG = 1.0 and Z.ARG = MATH_PI + -- LOG(Z) = COMPLEX_POLAR'(MATH_PI_OVER_2, MATH_PI_OVER_2) if + -- Z.MAG = 1.0 and Z.ARG = MATH_PI_OVER_2 + -- LOG(Z) = COMPLEX_POLAR'(MATH_PI_OVER_2, -MATH_PI_OVER_2) if + -- Z.MAG = 1.0 and Z.ARG = -MATH_PI_OVER_2 + -- LOG(Z) = COMPLEX_POLAR'(1.0, 0.0) if Z.MAG = MATH_E and + -- Z.ARG = 0.0 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Z.MAG /= 0.0 + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Error if Z.MAG = 0.0 + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function LOG2(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of logarithm base 2 of Z + -- Special values: + -- LOG2(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = 1.0 and + -- Z.ARG = 0.0 + -- LOG2(Z) = COMPLEX_POLAR'(1.0, 0.0) if Z.MAG = 2.0 and + -- Z.ARG = 0.0 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Z.MAG /= 0.0 + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Error if Z.MAG = 0.0 + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function LOG10(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of logarithm base 10 of Z + -- Special values: + -- LOG10(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = 1.0 and + -- Z.ARG = 0.0 + -- LOG10(Z) = COMPLEX_POLAR'(1.0, 0.0) if Z.MAG = 10.0 and + -- Z.ARG = 0.0 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Z.MAG /= 0.0 + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Error if Z.MAG = 0.0 + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function LOG(Z: in COMPLEX; BASE: in REAL) return COMPLEX; + -- Purpose: + -- Returns logarithm base BASE of Z + -- Special values: + -- LOG(MATH_CBASE_1, BASE) = MATH_CZERO + -- LOG(Z,BASE) = MATH_CBASE_1 if Z = COMPLEX'(BASE, 0.0) + -- Domain: + -- Z in COMPLEX and ABS(Z) /= 0.0 + -- BASE > 0.0 + -- BASE /= 1.0 + -- Error conditions: + -- Error if ABS(Z) = 0.0 + -- Error if BASE <= 0.0 + -- Error if BASE = 1.0 + -- Range: + -- LOG(Z,BASE) is mathematically unbounded + -- Notes: + -- None + + function LOG(Z: in COMPLEX_POLAR; BASE: in REAL ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of logarithm base BASE of Z + -- Special values: + -- LOG(Z, BASE) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = 1.0 and + -- Z.ARG = 0.0 + -- LOG(Z, BASE) = COMPLEX_POLAR'(1.0, 0.0) if Z.MAG = BASE and + -- Z.ARG = 0.0 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Z.MAG /= 0.0 + -- BASE > 0.0 + -- BASE /= 1.0 + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Error if Z.MAG = 0.0 + -- Error if BASE <= 0.0 + -- Error if BASE = 1.0 + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function SIN (Z : in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns sine of Z + -- Special values: + -- SIN(MATH_CZERO) = MATH_CZERO + -- SIN(Z) = MATH_CZERO if Z = COMPLEX'(MATH_PI, 0.0) + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- ABS(SIN(Z)) <= SQRT(SIN(Z.RE)*SIN(Z.RE) + + -- SINH(Z.IM)*SINH(Z.IM)) + -- Notes: + -- None + + function SIN (Z : in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of sine of Z + -- Special values: + -- SIN(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = 0.0 and + -- Z.ARG = 0.0 + -- SIN(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = MATH_PI and + -- Z.ARG = 0.0 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function COS (Z : in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns cosine of Z + -- Special values: + -- COS(Z) = MATH_CZERO if Z = COMPLEX'(MATH_PI_OVER_2, 0.0) + -- COS(Z) = MATH_CZERO if Z = COMPLEX'(-MATH_PI_OVER_2, 0.0) + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- ABS(COS(Z)) <= SQRT(COS(Z.RE)*COS(Z.RE) + + -- SINH(Z.IM)*SINH(Z.IM)) + -- Notes: + -- None + + + function COS (Z : in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of cosine of Z + -- Special values: + -- COS(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = MATH_PI_OVER_2 + -- and Z.ARG = 0.0 + -- COS(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = MATH_PI_OVER_2 + -- and Z.ARG = MATH_PI + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function SINH (Z : in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns hyperbolic sine of Z + -- Special values: + -- SINH(MATH_CZERO) = MATH_CZERO + -- SINH(Z) = MATH_CZERO if Z.RE = 0.0 and Z.IM = MATH_PI + -- SINH(Z) = MATH_CBASE_J if Z.RE = 0.0 and + -- Z.IM = MATH_PI_OVER_2 + -- SINH(Z) = -MATH_CBASE_J if Z.RE = 0.0 and + -- Z.IM = -MATH_PI_OVER_2 + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- ABS(SINH(Z)) <= SQRT(SINH(Z.RE)*SINH(Z.RE) + + -- SIN(Z.IM)*SIN(Z.IM)) + -- Notes: + -- None + + function SINH (Z : in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of hyperbolic sine of Z + -- Special values: + -- SINH(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = 0.0 and + -- Z.ARG = 0.0 + -- SINH(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = MATH_PI and + -- Z.ARG = MATH_PI_OVER_2 + -- SINH(Z) = COMPLEX_POLAR'(1.0, MATH_PI_OVER_2) if Z.MAG = + -- MATH_PI_OVER_2 and Z.ARG = MATH_PI_OVER_2 + -- SINH(Z) = COMPLEX_POLAR'(1.0, -MATH_PI_OVER_2) if Z.MAG = + -- MATH_PI_OVER_2 and Z.ARG = -MATH_PI_OVER_2 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function COSH (Z : in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns hyperbolic cosine of Z + -- Special values: + -- COSH(MATH_CZERO) = MATH_CBASE_1 + -- COSH(Z) = -MATH_CBASE_1 if Z.RE = 0.0 and Z.IM = MATH_PI + -- COSH(Z) = MATH_CZERO if Z.RE = 0.0 and Z.IM = MATH_PI_OVER_2 + -- COSH(Z) = MATH_CZERO if Z.RE = 0.0 and Z.IM = -MATH_PI_OVER_2 + -- Domain: + -- Z in COMPLEX + -- Error conditions: + -- None + -- Range: + -- ABS(COSH(Z)) <= SQRT(SINH(Z.RE)*SINH(Z.RE) + + -- COS(Z.IM)*COS(Z.IM)) + -- Notes: + -- None + + + function COSH (Z : in COMPLEX_POLAR ) return COMPLEX_POLAR; + -- Purpose: + -- Returns principal value of hyperbolic cosine of Z + -- Special values: + -- COSH(Z) = COMPLEX_POLAR'(1.0, 0.0) if Z.MAG = 0.0 and + -- Z.ARG = 0.0 + -- COSH(Z) = COMPLEX_POLAR'(1.0, MATH_PI) if Z.MAG = MATH_PI and + -- Z.ARG = MATH_PI_OVER_2 + -- COSH(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = + -- MATH_PI_OVER_2 and Z.ARG = MATH_PI_OVER_2 + -- COSH(Z) = COMPLEX_POLAR'(0.0, 0.0) if Z.MAG = + -- MATH_PI_OVER_2 and Z.ARG = -MATH_PI_OVER_2 + -- Domain: + -- Z in COMPLEX_POLAR and Z.ARG /= -MATH_PI + -- Error conditions: + -- Error if Z.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + -- + -- Arithmetic Operators + -- + + function "+" ( L: in COMPLEX; R: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns arithmetic addition of L and R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX + -- R in COMPLEX + -- Error conditions: + -- None + -- Range: + -- "+"(Z) is mathematically unbounded + -- Notes: + -- None + + function "+" ( L: in REAL; R: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns arithmetic addition of L and R + -- Special values: + -- None + -- Domain: + -- L in REAL + -- R in COMPLEX + -- Error conditions: + -- None + -- Range: + -- "+"(Z) is mathematically unbounded + -- Notes: + -- None + + function "+" ( L: in COMPLEX; R: in REAL ) return COMPLEX; + -- Purpose: + -- Returns arithmetic addition of L and R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX + -- R in REAL + -- Error conditions: + -- None + -- Range: + -- "+"(Z) is mathematically unbounded + -- Notes: + -- None + + function "+" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR) + return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic addition of L and R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Error if R.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + + function "+" ( L: in REAL; R: in COMPLEX_POLAR) return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic addition of L and R + -- Special values: + -- None + -- Domain: + -- L in REAL + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- Error conditions: + -- Error if R.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function "+" ( L: in COMPLEX_POLAR; R: in REAL) return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic addition of L and R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in REAL + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function "-" ( L: in COMPLEX; R: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns arithmetic subtraction of L minus R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX + -- R in COMPLEX + -- Error conditions: + -- None + -- Range: + -- "-"(Z) is mathematically unbounded + -- Notes: + -- None + + function "-" ( L: in REAL; R: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns arithmetic subtraction of L minus R + -- Special values: + -- None + -- Domain: + -- L in REAL + -- R in COMPLEX + -- Error conditions: + -- None + -- Range: + -- "-"(Z) is mathematically unbounded + -- Notes: + -- None + + function "-" ( L: in COMPLEX; R: in REAL ) return COMPLEX; + -- Purpose: + -- Returns arithmetic subtraction of L minus R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX + -- R in REAL + -- Error conditions: + -- None + -- Range: + -- "-"(Z) is mathematically unbounded + -- Notes: + -- None + + function "-" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR) + return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic subtraction of L minus R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Error if R.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function "-" ( L: in REAL; R: in COMPLEX_POLAR) return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic subtraction of L minus R + -- Special values: + -- None + -- Domain: + -- L in REAL + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- Error conditions: + -- Error if R.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + + function "-" ( L: in COMPLEX_POLAR; R: in REAL) return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic subtraction of L minus R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in REAL + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function "*" ( L: in COMPLEX; R: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns arithmetic multiplication of L and R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX + -- R in COMPLEX + -- Error conditions: + -- None + -- Range: + -- "*"(Z) is mathematically unbounded + -- Notes: + -- None + + function "*" ( L: in REAL; R: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns arithmetic multiplication of L and R + -- Special values: + -- None + -- Domain: + -- L in REAL + -- R in COMPLEX + -- Error conditions: + -- None + -- Range: + -- "*"(Z) is mathematically unbounded + -- Notes: + -- None + + function "*" ( L: in COMPLEX; R: in REAL ) return COMPLEX; + -- Purpose: + -- Returns arithmetic multiplication of L and R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX + -- R in REAL + -- Error conditions: + -- None + + -- Range: + -- "*"(Z) is mathematically unbounded + -- Notes: + -- None + + function "*" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR) + return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic multiplication of L and R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Error if R.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function "*" ( L: in REAL; R: in COMPLEX_POLAR) return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic multiplication of L and R + -- Special values: + -- None + -- Domain: + -- L in REAL + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- Error conditions: + -- Error if R.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function "*" ( L: in COMPLEX_POLAR; R: in REAL) return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic multiplication of L and R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in REAL + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + + function "/" ( L: in COMPLEX; R: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns arithmetic division of L by R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX + -- R in COMPLEX and R /= MATH_CZERO + -- Error conditions: + -- Error if R = MATH_CZERO + -- Range: + -- "/"(Z) is mathematically unbounded + -- Notes: + -- None + + function "/" ( L: in REAL; R: in COMPLEX ) return COMPLEX; + -- Purpose: + -- Returns arithmetic division of L by R + -- Special values: + -- None + -- Domain: + -- L in REAL + -- R in COMPLEX and R /= MATH_CZERO + -- Error conditions: + -- Error if R = MATH_CZERO + -- Range: + -- "/"(Z) is mathematically unbounded + -- Notes: + -- None + + function "/" ( L: in COMPLEX; R: in REAL ) return COMPLEX; + -- Purpose: + -- Returns arithmetic division of L by R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX + -- R in REAL and R /= 0.0 + -- Error conditions: + -- Error if R = 0.0 + -- Range: + -- "/"(Z) is mathematically unbounded + -- Notes: + -- None + + function "/" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR) + return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic division of L by R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- R.MAG > 0.0 + -- Error conditions: + -- Error if R.MAG <= 0.0 + -- Error if L.ARG = -MATH_PI + -- Error if R.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function "/" ( L: in REAL; R: in COMPLEX_POLAR) return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic division of L by R + -- Special values: + -- None + -- Domain: + -- L in REAL + -- R in COMPLEX_POLAR and R.ARG /= -MATH_PI + -- R.MAG > 0.0 + -- Error conditions: + -- Error if R.MAG <= 0.0 + -- Error if R.ARG = -MATH_PI + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None + + function "/" ( L: in COMPLEX_POLAR; R: in REAL) return COMPLEX_POLAR; + -- Purpose: + -- Returns arithmetic division of L by R + -- Special values: + -- None + -- Domain: + -- L in COMPLEX_POLAR and L.ARG /= -MATH_PI + -- R /= 0.0 + -- Error conditions: + -- Error if L.ARG = -MATH_PI + -- Error if R = 0.0 + -- Range: + -- result.MAG >= 0.0 + -- -MATH_PI < result.ARG <= MATH_PI + -- Notes: + -- None +end MATH_COMPLEX; diff --git a/lib/Standard/ieee/math_complex_body.vhd b/lib/Standard/ieee/math_complex_body.vhd new file mode 100644 index 0000000..97fb6bb --- /dev/null +++ b/lib/Standard/ieee/math_complex_body.vhd @@ -0,0 +1,1604 @@ +------------------------------------------------------------------------ +-- +-- Copyright 1996 by IEEE. All rights reserved. +-- +-- This source file is an informative part of IEEE Std 1076.2-1996, IEEE Standard +-- VHDL Mathematical Packages. This source file may not be copied, sold, or +-- included with software that is sold without written permission from the IEEE +-- Standards Department. This source file may be used to implement this standard +-- and may be distributed in compiled form in any manner so long as the +-- compiled form does not allow direct decompilation of the original source file. +-- This source file may be copied for individual use between licensed users. +-- This source file is provided on an AS IS basis. The IEEE disclaims ANY +-- WARRANTY EXPRESS OR IMPLIED INCLUDING ANY WARRANTY OF MERCHANTABILITY +-- AND FITNESS FOR USE FOR A PARTICULAR PURPOSE. The user of the source +-- file shall indemnify and hold IEEE harmless from any damages or liability +-- arising out of the use thereof. +-- +-- Title: Standard VHDL Mathematical Packages (IEEE Std 1076.2-1996, +-- MATH_COMPLEX) +-- +-- Library: This package shall be compiled into a library +-- symbolically named IEEE. +-- +-- Developers: IEEE DASC VHDL Mathematical Packages Working Group +-- +-- Purpose: This package body is a nonnormative implementation of the +-- functionality defined in the MATH_COMPLEX package declaration. +-- +-- Limitation: The values generated by the functions in this package may +-- vary from platform to platform, and the precision of results +-- is only guaranteed to be the minimum required by IEEE Std 1076 +-- -1993. +-- +-- Notes: +-- The "package declaration" defines the types, subtypes, and +-- declarations of MATH_COMPLEX. +-- The standard mathematical definition and conventional meaning +-- of the mathematical functions that are part of this standard +-- represent the formal semantics of the implementation of the +-- MATH_COMPLEX package declaration. The purpose of the +-- MATH_COMPLEX package body is to clarify such semantics and +-- provide a guideline for implementations to verify their +-- implementation of MATH_COMPLEX. Tool developers may choose to +-- implement the package body in the most efficient manner +-- available to them. +-- +-- ----------------------------------------------------------------------------- +-- Version : 1.5 +-- Date : 24 July 1996 +-- ----------------------------------------------------------------------------- + +use WORK.MATH_REAL.all; + +package body MATH_COMPLEX is + + -- + -- Equality and Inequality Operators for COMPLEX_POLAR + -- + function "=" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR ) return BOOLEAN + is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns FALSE on error + begin + -- Check validity of input arguments + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in =(L,R)" + severity ERROR; + return FALSE; + end if; + + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in =(L,R)" + severity ERROR; + return FALSE; + end if; + + -- Get special values + if ( L.MAG = 0.0 and R.MAG = 0.0 ) then + return TRUE; + end if; + + -- Get value for general case + if ( L.MAG = R.MAG and L.ARG = R.ARG ) then + return TRUE; + end if; + + return FALSE; + end "="; + + + function "/=" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR ) return BOOLEAN + is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns FALSE on error + begin + -- Check validity of input arguments + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in /=(L,R)" + severity ERROR; + return FALSE; + end if; + + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in /=(L,R)" + severity ERROR; + return FALSE; + end if; + + -- Get special values + if ( L.MAG = 0.0 and R.MAG = 0.0 ) then + return FALSE; + end if; + + -- Get value for general case + if ( L.MAG = R.MAG and L.ARG = R.ARG ) then + return FALSE; + end if; + + return TRUE; + end "/="; + + -- + -- Other Functions Start Here + -- + + function CMPLX(X: in REAL; Y: in REAL := 0.0 ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(X, Y); + end CMPLX; + + + function GET_PRINCIPAL_VALUE(X: in REAL ) return PRINCIPAL_VALUE is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + variable TEMP: REAL; + begin + -- Check if already a principal value + if ( X > -MATH_PI and X <= MATH_PI ) then + return PRINCIPAL_VALUE'(X); + end if; + + -- Get principal value + TEMP := X; + while ( TEMP <= -MATH_PI ) loop + TEMP := TEMP + MATH_2_PI; + end loop; + while (TEMP > MATH_PI ) loop + TEMP := TEMP - MATH_2_PI; + end loop; + + return PRINCIPAL_VALUE'(TEMP); + end GET_PRINCIPAL_VALUE; + + function COMPLEX_TO_POLAR(Z: in COMPLEX ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + variable TEMP: REAL; + begin + -- Get value for special cases + if ( Z.RE = 0.0 ) then + if ( Z.IM = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + elsif ( Z.IM > 0.0 ) then + return COMPLEX_POLAR'(Z.IM, MATH_PI_OVER_2); + else + return COMPLEX_POLAR'(-Z.IM, -MATH_PI_OVER_2); + end if; + end if; + + if ( Z.IM = 0.0 ) then + if ( Z.RE = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + elsif ( Z.RE > 0.0 ) then + return COMPLEX_POLAR'(Z.RE, 0.0); + else + return COMPLEX_POLAR'(-Z.RE, MATH_PI); + end if; + end if; + + -- Get principal value for general case + TEMP := ARCTAN(Z.IM, Z.RE); + + return COMPLEX_POLAR'(SQRT(Z.RE*Z.RE + Z.IM*Z.IM), + GET_PRINCIPAL_VALUE(TEMP)); + end COMPLEX_TO_POLAR; + + function POLAR_TO_COMPLEX(Z: in COMPLEX_POLAR ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns MATH_CZERO on error + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in POLAR_TO_COMPLEX(Z)" + severity ERROR; + return MATH_CZERO; + end if; + + -- Get value for general case + return COMPLEX'( Z.MAG*COS(Z.ARG), Z.MAG*SIN(Z.ARG) ); + end POLAR_TO_COMPLEX; + + + function "ABS"(Z: in COMPLEX ) return POSITIVE_REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ABS(Z) = SQRT(Z.RE*Z.RE + Z.IM*Z.IM) + + begin + -- Get value for general case + return POSITIVE_REAL'(SQRT(Z.RE*Z.RE + Z.IM*Z.IM)); + end "ABS"; + + function "ABS"(Z: in COMPLEX_POLAR ) return POSITIVE_REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ABS(Z) = Z.MAG + -- b) Returns 0.0 on error + + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in ABS(Z)" + severity ERROR; + return 0.0; + end if; + + -- Get value for general case + return Z.MAG; + end "ABS"; + + + function ARG(Z: in COMPLEX ) return PRINCIPAL_VALUE is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ARG(Z) = ARCTAN(Z.IM, Z.RE) + + variable ZTEMP : COMPLEX_POLAR; + begin + -- Get value for general case + ZTEMP := COMPLEX_TO_POLAR(Z); + return ZTEMP.ARG; + end ARG; + + function ARG(Z: in COMPLEX_POLAR ) return PRINCIPAL_VALUE is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ARG(Z) = Z.ARG + -- b) Returns 0.0 on error + + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in ARG(Z)" + severity ERROR; + return 0.0; + end if; + + -- Get value for general case + return Z.ARG; + end ARG; + + function "-" (Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns -x -jy for Z = x + jy + begin + -- Get value for general case + return COMPLEX'(-Z.RE, -Z.IM); + end "-"; + + function "-" (Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (Z.MAG, Z.ARG + MATH_PI) + -- b) Returns Z on error + variable TEMP: REAL; + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in -(Z)" + severity ERROR; + return Z; + end if; + + -- Get principal value for general case + TEMP := REAL'(Z.ARG) + MATH_PI; + + return COMPLEX_POLAR'(Z.MAG, GET_PRINCIPAL_VALUE(TEMP)); + end "-"; + + function CONJ (Z: in COMPLEX) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns x - jy for Z = x + jy + begin + -- Get value for general case + return COMPLEX'(Z.RE, -Z.IM); + end CONJ; + + function CONJ (Z: in COMPLEX_POLAR) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX conjugate (Z.MAG, -Z.ARG) + -- b) Returns Z on error + -- + variable TEMP: PRINCIPAL_VALUE; + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in CONJ(Z)" + severity ERROR; + return Z; + end if; + + -- Get principal value for general case + if ( Z.ARG = MATH_PI or Z.ARG = 0.0 ) then + TEMP := Z.ARG; + else + TEMP := -Z.ARG; + end if; + + return COMPLEX_POLAR'(Z.MAG, TEMP); + end CONJ; + + function SQRT(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + variable ZTEMP : COMPLEX_POLAR; + variable ZOUT : COMPLEX; + variable TMAG : REAL; + variable TARG : REAL; + begin + -- Get value for special cases + if ( Z = MATH_CZERO ) then + return MATH_CZERO; + end if; + + -- Get value for general case + ZTEMP := COMPLEX_TO_POLAR(Z); + TMAG := SQRT(ZTEMP.MAG); + TARG := 0.5*ZTEMP.ARG; + + if ( COS(TARG) > 0.0 ) then + ZOUT.RE := TMAG*COS(TARG); + ZOUT.IM := TMAG*SIN(TARG); + return ZOUT; + end if; + + if ( COS(TARG) < 0.0 ) then + ZOUT.RE := TMAG*COS(TARG + MATH_PI); + ZOUT.IM := TMAG*SIN(TARG + MATH_PI); + return ZOUT; + end if; + + if ( SIN(TARG) > 0.0 ) then + ZOUT.RE := 0.0; + ZOUT.IM := TMAG*SIN(TARG); + return ZOUT; + end if; + + ZOUT.RE := 0.0; + ZOUT.IM := TMAG*SIN(TARG + MATH_PI); + return ZOUT; + end SQRT; + + function SQRT(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns Z on error + + variable ZOUT : COMPLEX_POLAR; + variable TMAG : REAL; + variable TARG : REAL; + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in SQRT(Z)" + severity ERROR; + return Z; + end if; + + -- Get value for special cases + if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then + return Z; + end if; + + -- Get principal value for general case + TMAG := SQRT(Z.MAG); + TARG := 0.5*Z.ARG; + + ZOUT.MAG := POSITIVE_REAL'(TMAG); + + if ( COS(TARG) < 0.0 ) then + TARG := TARG + MATH_PI; + end if; + + if ( (COS(TARG) = 0.0) and (SIN(TARG) < 0.0) ) then + TARG := TARG + MATH_PI; + end if; + + ZOUT.ARG := GET_PRINCIPAL_VALUE(TARG); + return ZOUT; + end SQRT; + + function EXP(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + + variable TEMP: REAL; + begin + -- Get value for special cases + if ( Z = MATH_CZERO ) then + return MATH_CBASE_1; + end if; + + if ( Z.RE = 0.0 ) then + if ( Z.IM = MATH_PI or Z.IM = -MATH_PI ) then + return COMPLEX'(-1.0, 0.0); + end if; + + if ( Z.IM = MATH_PI_OVER_2 ) then + return MATH_CBASE_J; + end if; + + if ( Z.IM = -MATH_PI_OVER_2 ) then + return COMPLEX'(0.0, -1.0); + end if; + end if; + + -- Get value for general case + TEMP := EXP(Z.RE); + return COMPLEX'(TEMP*COS(Z.IM), TEMP*SIN(Z.IM)); + end EXP; + + function EXP(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns Z on error + + variable ZTEMP : COMPLEX; + variable temp: REAL; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in EXP(Z)" + severity ERROR; + return Z; + end if; + + -- Get value for special cases + if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(1.0, 0.0); + end if; + + if ( Z.MAG = MATH_PI and (Z.ARG = MATH_PI_OVER_2 or + Z.ARG = -MATH_PI_OVER_2 )) then + return COMPLEX_POLAR'(1.0, MATH_PI); + end if; + + if ( Z.MAG = MATH_PI_OVER_2 ) then + if ( Z.ARG = MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(1.0, MATH_PI_OVER_2); + end if; + + if ( Z.ARG = -MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(1.0, -MATH_PI_OVER_2); + end if; + end if; + + -- Get principal value for general case + ZTEMP := POLAR_TO_COMPLEX(Z); + ZOUT.MAG := POSITIVE_REAL'(EXP(ZTEMP.RE)); + ZOUT.ARG := GET_PRINCIPAL_VALUE(ZTEMP.IM); + + return ZOUT; + end EXP; + + function LOG(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX'(REAL'LOW, 0.0) on error + + variable ZTEMP : COMPLEX_POLAR; + variable TEMP : REAL; + begin + -- Check validity of input arguments + if ( Z.RE = 0.0 and Z.IM = 0.0 ) then + assert FALSE + report "Z.RE = 0.0 and Z.IM = 0.0 in LOG(Z)" + severity ERROR; + return COMPLEX'(REAL'LOW, 0.0); + end if; + + -- Get value for special cases + if ( Z.IM = 0.0 ) then + if ( Z.RE = -1.0 ) then + return COMPLEX'(0.0, MATH_PI); + end if; + if ( Z.RE = MATH_E ) then + return MATH_CBASE_1; + end if; + if ( Z.RE = 1.0 ) then + return MATH_CZERO; + end if; + end if; + + if ( Z.RE = 0.0 ) then + if (Z.IM = 1.0) then + return COMPLEX'(0.0, MATH_PI_OVER_2); + end if; + if (Z.IM = -1.0) then + return COMPLEX'(0.0, -MATH_PI_OVER_2); + end if; + end if; + + -- Get value for general case + ZTEMP := COMPLEX_TO_POLAR(Z); + TEMP := LOG(ZTEMP.MAG); + return COMPLEX'(TEMP, ZTEMP.ARG); + end LOG; + + function LOG2(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX'(REAL'LOW, 0.0) on error + + variable ZTEMP : COMPLEX_POLAR; + variable TEMP : REAL; + begin + + -- Check validity of input arguments + if ( Z.RE = 0.0 and Z.IM = 0.0 ) then + assert FALSE + report "Z.RE = 0.0 and Z.IM = 0.0 in LOG2(Z)" + severity ERROR; + return COMPLEX'(REAL'LOW, 0.0); + end if; + + -- Get value for special cases + if ( Z.IM = 0.0 ) then + if ( Z.RE = 2.0 ) then + return MATH_CBASE_1; + end if; + if ( Z.RE = 1.0 ) then + return MATH_CZERO; + end if; + end if; + + -- Get value for general case + ZTEMP := COMPLEX_TO_POLAR(Z); + TEMP := MATH_LOG2_OF_E*LOG(ZTEMP.MAG); + return COMPLEX'(TEMP, MATH_LOG2_OF_E*ZTEMP.ARG); + end LOG2; + + function LOG10(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX'(REAL'LOW, 0.0) on error + + variable ZTEMP : COMPLEX_POLAR; + variable TEMP : REAL; + begin + -- Check validity of input arguments + if ( Z.RE = 0.0 and Z.IM = 0.0 ) then + assert FALSE + report "Z.RE = 0.0 and Z.IM = 0.0 in LOG10(Z)" + severity ERROR; + return COMPLEX'(REAL'LOW, 0.0); + end if; + + -- Get value for special cases + if ( Z.IM = 0.0 ) then + if ( Z.RE = 10.0 ) then + return MATH_CBASE_1; + end if; + if ( Z.RE = 1.0 ) then + return MATH_CZERO; + end if; + end if; + + -- Get value for general case + ZTEMP := COMPLEX_TO_POLAR(Z); + TEMP := MATH_LOG10_OF_E*LOG(ZTEMP.MAG); + return COMPLEX'(TEMP, MATH_LOG10_OF_E*ZTEMP.ARG); + end LOG10; + + + function LOG(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR(REAL'HIGH, MATH_PI) on error + + variable ZTEMP : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.MAG <= 0.0 ) then + assert FALSE + report "Z.MAG <= 0.0 in LOG(Z)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in LOG(Z)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + -- Compute value for special cases + if (Z.MAG = 1.0 ) then + if ( Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.ARG = MATH_PI ) then + return COMPLEX_POLAR'(MATH_PI, MATH_PI_OVER_2); + end if; + + if ( Z.ARG = MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(MATH_PI_OVER_2, MATH_PI_OVER_2); + end if; + + if ( Z.ARG = -MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(MATH_PI_OVER_2, -MATH_PI_OVER_2); + end if; + end if; + + if ( Z.MAG = MATH_E and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(1.0, 0.0); + end if; + + -- Compute value for general case + ZTEMP.RE := LOG(Z.MAG); + ZTEMP.IM := Z.ARG; + ZOUT := COMPLEX_TO_POLAR(ZTEMP); + return ZOUT; + end LOG; + + + + function LOG2(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR(REAL'HIGH, MATH_PI) on error + + variable ZTEMP : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.MAG <= 0.0 ) then + assert FALSE + report "Z.MAG <= 0.0 in LOG2(Z)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in LOG2(Z)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + -- Compute value for special cases + if (Z.MAG = 1.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.MAG = 2.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(1.0, 0.0); + end if; + + -- Compute value for general case + ZTEMP.RE := MATH_LOG2_OF_E*LOG(Z.MAG); + ZTEMP.IM := MATH_LOG2_OF_E*Z.ARG; + ZOUT := COMPLEX_TO_POLAR(ZTEMP); + return ZOUT; + end LOG2; + + function LOG10(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR(REAL'HIGH, MATH_PI) on error + variable ZTEMP : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.MAG <= 0.0 ) then + assert FALSE + report "Z.MAG <= 0.0 in LOG10(Z)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in LOG10(Z)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + -- Compute value for special cases + if (Z.MAG = 1.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.MAG = 10.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(1.0, 0.0); + end if; + + -- Compute value for general case + ZTEMP.RE := MATH_LOG10_OF_E*LOG(Z.MAG); + ZTEMP.IM := MATH_LOG10_OF_E*Z.ARG; + ZOUT := COMPLEX_TO_POLAR(ZTEMP); + return ZOUT; + end LOG10; + + function LOG(Z: in COMPLEX; BASE: in REAL ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX'(REAL'LOW, 0.0) on error + + variable ZTEMP : COMPLEX_POLAR; + variable TEMPRE : REAL; + variable TEMPIM : REAL; + begin + -- Check validity of input arguments + if ( Z.RE = 0.0 and Z.IM = 0.0 ) then + assert FALSE + report "Z.RE = 0.0 and Z.IM = 0.0 in LOG(Z,BASE)" + severity ERROR; + return COMPLEX'(REAL'LOW, 0.0); + end if; + + if ( BASE <= 0.0 or BASE = 1.0 ) then + assert FALSE + report "BASE <= 0.0 or BASE = 1.0 in LOG(Z,BASE)" + severity ERROR; + return COMPLEX'(REAL'LOW, 0.0); + end if; + + -- Get value for special cases + if ( Z.IM = 0.0 ) then + if ( Z.RE = BASE ) then + return MATH_CBASE_1; + end if; + if ( Z.RE = 1.0 ) then + return MATH_CZERO; + end if; + end if; + + -- Get value for general case + ZTEMP := COMPLEX_TO_POLAR(Z); + TEMPRE := LOG(ZTEMP.MAG, BASE); + TEMPIM := ZTEMP.ARG/LOG(BASE); + return COMPLEX'(TEMPRE, TEMPIM); + end LOG; + + function LOG(Z: in COMPLEX_POLAR; BASE: in REAL ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR(REAL'HIGH, MATH_PI) on error + + variable ZTEMP : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.MAG <= 0.0 ) then + assert FALSE + report "Z.MAG <= 0.0 in LOG(Z,BASE)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + if ( BASE <= 0.0 or BASE = 1.0 ) then + assert FALSE + report "BASE <= 0.0 or BASE = 1.0 in LOG(Z,BASE)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in LOG(Z,BASE)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, MATH_PI); + end if; + + -- Compute value for special cases + if (Z.MAG = 1.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.MAG = BASE and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(1.0, 0.0); + end if; + + -- Compute value for general case + ZTEMP.RE := LOG(Z.MAG, BASE); + ZTEMP.IM := Z.ARG/LOG(BASE); + ZOUT := COMPLEX_TO_POLAR(ZTEMP); + return ZOUT; + end LOG; + + + function SIN(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + -- Get value for special cases + if ( Z.IM = 0.0 ) then + if ( Z.RE = 0.0 or Z.RE = MATH_PI) then + return MATH_CZERO; + end if; + end if; + + -- Get value for general case + return COMPLEX'(SIN(Z.RE)*COSH(Z.IM), COS(Z.RE)*SINH(Z.IM)); + end SIN; + + function SIN(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR(0.0, 0.0) on error + + variable Z1, Z2 : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in SIN(Z)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Compute value for special cases + if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.MAG = MATH_PI and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Compute value for general case + Z1 := POLAR_TO_COMPLEX(Z); + Z2 := COMPLEX'(SIN(Z1.RE)*COSH(Z1.IM), COS(Z1.RE)*SINH(Z1.IM)); + ZOUT := COMPLEX_TO_POLAR(Z2); + return ZOUT; + end SIN; + + function COS(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + + + -- Get value for special cases + if ( Z.IM = 0.0 ) then + if ( Z.RE = MATH_PI_OVER_2 or Z.RE = -MATH_PI_OVER_2) then + return MATH_CZERO; + end if; + end if; + + -- Get value for general case + return COMPLEX'(COS(Z.RE)*COSH(Z.IM), -SIN(Z.RE)*SINH(Z.IM)); + end COS; + + function COS(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR(0.0, 0.0) on error + + variable Z1, Z2 : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in COS(Z)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Compute value for special cases + if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = MATH_PI ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Compute value for general case + Z1 := POLAR_TO_COMPLEX(Z); + Z2 := COMPLEX'(COS(Z1.RE)*COSH(Z1.IM), -SIN(Z1.RE)*SINH(Z1.IM)); + ZOUT := COMPLEX_TO_POLAR(Z2); + return ZOUT; + end COS; + + function SINH(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + -- Get value for special cases + if ( Z.RE = 0.0 ) then + if ( Z.IM = 0.0 or Z.IM = MATH_PI ) then + return MATH_CZERO; + end if; + + + + if ( Z.IM = MATH_PI_OVER_2 ) then + return MATH_CBASE_J; + end if; + + if ( Z.IM = -MATH_PI_OVER_2 ) then + return -MATH_CBASE_J; + end if; + end if; + + -- Get value for general case + return COMPLEX'(SINH(Z.RE)*COS(Z.IM), COSH(Z.RE)*SIN(Z.IM)); + end SINH; + + function SINH(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR(0.0, 0.0) on error + + variable Z1, Z2 : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in SINH(Z)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Compute value for special cases + if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.MAG = MATH_PI and Z.ARG = MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(1.0, MATH_PI_OVER_2); + end if; + + if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = -MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(1.0, -MATH_PI_OVER_2); + end if; + + -- Compute value for general case + Z1 := POLAR_TO_COMPLEX(Z); + Z2 := COMPLEX'(SINH(Z1.RE)*COS(Z1.IM), COSH(Z1.RE)*SIN(Z1.IM)); + ZOUT := COMPLEX_TO_POLAR(Z2); + return ZOUT; + end SINH; + + + function COSH(Z: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + -- Get value for special cases + if ( Z.RE = 0.0 ) then + if ( Z.IM = 0.0 ) then + return MATH_CBASE_1; + end if; + + if ( Z.IM = MATH_PI ) then + return -MATH_CBASE_1; + end if; + + if ( Z.IM = MATH_PI_OVER_2 or Z.IM = -MATH_PI_OVER_2 ) then + return MATH_CZERO; + end if; + end if; + + -- Get value for general case + return COMPLEX'(COSH(Z.RE)*COS(Z.IM), SINH(Z.RE)*SIN(Z.IM)); + end COSH; + + function COSH(Z: in COMPLEX_POLAR ) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR(0.0, 0.0) on error + + variable Z1, Z2 : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( Z.ARG = -MATH_PI ) then + assert FALSE + report "Z.ARG = -MATH_PI in COSH(Z)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Compute value for special cases + if ( Z.MAG = 0.0 and Z.ARG = 0.0 ) then + return COMPLEX_POLAR'(1.0, 0.0); + end if; + + if ( Z.MAG = MATH_PI and Z.ARG = MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(1.0, MATH_PI); + end if; + + if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( Z.MAG = MATH_PI_OVER_2 and Z.ARG = -MATH_PI_OVER_2 ) then + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Compute value for general case + Z1 := POLAR_TO_COMPLEX(Z); + Z2 := COMPLEX'(COSH(Z1.RE)*COS(Z1.IM), SINH(Z1.RE)*SIN(Z1.IM)); + ZOUT := COMPLEX_TO_POLAR(Z2); + return ZOUT; + end COSH; + + + -- + -- Arithmetic Operators + -- + function "+" ( L: in COMPLEX; R: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L.RE + R.RE, L.IM + R.IM); + end "+"; + + function "+" ( L: in REAL; R: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L + R.RE, R.IM); + end "+"; + + function "+" ( L: in COMPLEX; R: in REAL ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L.RE + R, L.IM); + end "+"; + + function "+" (L: in COMPLEX_POLAR; R: in COMPLEX_POLAR) + return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + -- + variable ZL, ZR : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in +(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in +(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZL := POLAR_TO_COMPLEX( L ); + ZR := POLAR_TO_COMPLEX( R ); + ZOUT := COMPLEX_TO_POLAR(COMPLEX'(ZL.RE + ZR.RE, ZL.IM +ZR.IM)); + return ZOUT; + end "+"; + + function "+" ( L: in REAL; R: in COMPLEX_POLAR) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + variable ZR : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in +(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZR := POLAR_TO_COMPLEX( R ); + ZOUT := COMPLEX_TO_POLAR(COMPLEX'(L + ZR.RE, ZR.IM)); + return ZOUT; + end "+"; + + function "+" ( L: in COMPLEX_POLAR; R: in REAL) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + -- + variable ZL : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in +(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZL := POLAR_TO_COMPLEX( L ); + ZOUT := COMPLEX_TO_POLAR(COMPLEX'(ZL.RE + R, ZL.IM)); + return ZOUT; + end "+"; + + function "-" ( L: in COMPLEX; R: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L.RE - R.RE, L.IM - R.IM); + end "-"; + + function "-" ( L: in REAL; R: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L - R.RE, -1.0 * R.IM); + end "-"; + + function "-" ( L: in COMPLEX; R: in REAL ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L.RE - R, L.IM); + end "-"; + + function "-" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR) + return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + -- + variable ZL, ZR : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in -(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in -(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + -- Get principal value + ZL := POLAR_TO_COMPLEX( L ); + ZR := POLAR_TO_COMPLEX( R ); + ZOUT := COMPLEX_TO_POLAR(COMPLEX'(ZL.RE - ZR.RE, ZL.IM -ZR.IM)); + return ZOUT; + end "-"; + + function "-" ( L: in REAL; R: in COMPLEX_POLAR) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + -- + variable ZR : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in -(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZR := POLAR_TO_COMPLEX( R ); + ZOUT := COMPLEX_TO_POLAR(COMPLEX'(L - ZR.RE, -1.0*ZR.IM)); + return ZOUT; + end "-"; + + function "-" ( L: in COMPLEX_POLAR; R: in REAL) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + -- + variable ZL : COMPLEX; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in -(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZL := POLAR_TO_COMPLEX( L ); + ZOUT := COMPLEX_TO_POLAR(COMPLEX'(ZL.RE - R, ZL.IM)); + return ZOUT; + end "-"; + + + function "*" ( L: in COMPLEX; R: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L.RE * R.RE - L.IM * R.IM, L.RE * R.IM + L.IM * R.RE); + end "*"; + + + function "*" ( L: in REAL; R: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L * R.RE, L * R.IM); + end "*"; + + function "*" ( L: in COMPLEX; R: in REAL ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + return COMPLEX'(L.RE * R, L.IM * R); + end "*"; + + function "*" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR) + return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + -- + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in *(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in *(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZOUT.MAG := L.MAG * R.MAG; + ZOUT.ARG := GET_PRINCIPAL_VALUE(L.ARG + R.ARG); + + return ZOUT; + end "*"; + + function "*" ( L: in REAL; R: in COMPLEX_POLAR) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + -- + variable ZL : COMPLEX_POLAR; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in *(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZL.MAG := POSITIVE_REAL'(ABS(L)); + if ( L < 0.0 ) then + ZL.ARG := MATH_PI; + else + ZL.ARG := 0.0; + end if; + + ZOUT.MAG := ZL.MAG * R.MAG; + ZOUT.ARG := GET_PRINCIPAL_VALUE(ZL.ARG + R.ARG); + + return ZOUT; + end "*"; + + function "*" ( L: in COMPLEX_POLAR; R: in REAL) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(0.0, 0.0) on error + -- + variable ZR : COMPLEX_POLAR; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in *(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZR.MAG := POSITIVE_REAL'(ABS(R)); + if ( R < 0.0 ) then + ZR.ARG := MATH_PI; + else + ZR.ARG := 0.0; + end if; + + ZOUT.MAG := L.MAG * ZR.MAG; + ZOUT.ARG := GET_PRINCIPAL_VALUE(L.ARG + ZR.ARG); + + return ZOUT; + end "*"; + + function "/" ( L: in COMPLEX; R: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX'(REAL'HIGH, 0.0) on error + -- + variable TEMP : REAL := R.RE*R.RE + R.IM*R.IM; + begin + -- Check validity of input arguments + if (TEMP = 0.0) then + assert FALSE + report "Attempt to divide COMPLEX by (0.0, 0.0)" + severity ERROR; + return COMPLEX'(REAL'HIGH, 0.0); + end if; + + -- Get value + return COMPLEX'( (L.RE * R.RE + L.IM * R.IM) / TEMP, + (L.IM * R.RE - L.RE * R.IM) / TEMP); + end "/"; + + function "/" ( L: in REAL; R: in COMPLEX ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX'(REAL'HIGH, 0.0) on error + -- + variable TEMP : REAL := R.RE*R.RE + R.IM*R.IM; + begin + -- Check validity of input arguments + if (TEMP = 0.0) then + assert FALSE + report "Attempt to divide COMPLEX by (0.0, 0.0)" + severity ERROR; + return COMPLEX'(REAL'HIGH, 0.0); + end if; + + -- Get value + TEMP := L / TEMP; + return COMPLEX'( TEMP * R.RE, -TEMP * R.IM ); + end "/"; + + function "/" ( L: in COMPLEX; R: in REAL ) return COMPLEX is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX'(REAL'HIGH, 0.0) on error + begin + -- Check validity of input arguments + if (R = 0.0) then + assert FALSE + report "Attempt to divide COMPLEX by 0.0" + severity ERROR; + return COMPLEX'(REAL'HIGH, 0.0); + end if; + + -- Get value + return COMPLEX'(L.RE / R, L.IM / R); + end "/"; + + + function "/" ( L: in COMPLEX_POLAR; R: in COMPLEX_POLAR) + return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(REAL'HIGH, 0.0) on error + -- + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if (R.MAG = 0.0) then + assert FALSE + report "Attempt to divide COMPLEX_POLAR by (0.0, 0.0)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, 0.0); + end if; + + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in /(L,R)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, 0.0); + end if; + + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_PI in /(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZOUT.MAG := L.MAG/R.MAG; + ZOUT.ARG := GET_PRINCIPAL_VALUE(L.ARG - R.ARG); + + return ZOUT; + end "/"; + + function "/" ( L: in COMPLEX_POLAR; R: in REAL) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(REAL'HIGH, 0.0) on error + -- + variable ZR : COMPLEX_POLAR; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if (R = 0.0) then + assert FALSE + report "Attempt to divide COMPLEX_POLAR by 0.0" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, 0.0); + end if; + + if ( L.ARG = -MATH_PI ) then + assert FALSE + report "L.ARG = -MATH_PI in /(L,R)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, 0.0); + end if; + + -- Get principal value + ZR.MAG := POSITIVE_REAL'(ABS(R)); + if R < 0.0 then + ZR.ARG := MATH_PI; + else + ZR.ARG := 0.0; + end if; + + ZOUT.MAG := L.MAG/ZR.MAG; + ZOUT.ARG := GET_PRINCIPAL_VALUE(L.ARG - ZR.ARG); + + return ZOUT; + end "/"; + + function "/" ( L: in REAL; R: in COMPLEX_POLAR) return COMPLEX_POLAR is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns COMPLEX_POLAR'(REAL'HIGH, 0.0) on error + -- + variable ZL : COMPLEX_POLAR; + variable ZOUT : COMPLEX_POLAR; + begin + -- Check validity of input arguments + if (R.MAG = 0.0) then + assert FALSE + report "Attempt to divide COMPLEX_POLAR by (0.0, 0.0)" + severity ERROR; + return COMPLEX_POLAR'(REAL'HIGH, 0.0); + end if; + + if ( R.ARG = -MATH_PI ) then + assert FALSE + report "R.ARG = -MATH_P in /(L,R)" + severity ERROR; + return COMPLEX_POLAR'(0.0, 0.0); + end if; + + -- Get principal value + ZL.MAG := POSITIVE_REAL'(ABS(L)); + if L < 0.0 then + ZL.ARG := MATH_PI; + else + ZL.ARG := 0.0; + end if; + + ZOUT.MAG := ZL.MAG/R.MAG; + ZOUT.ARG := GET_PRINCIPAL_VALUE(ZL.ARG - R.ARG); + + return ZOUT; + end "/"; + +end MATH_COMPLEX; diff --git a/lib/Standard/ieee/math_real.vhd b/lib/Standard/ieee/math_real.vhd new file mode 100644 index 0000000..ca1cec3 --- /dev/null +++ b/lib/Standard/ieee/math_real.vhd @@ -0,0 +1,628 @@ +------------------------------------------------------------------------ +-- +-- Copyright 1996 by IEEE. All rights reserved. +-- +-- This source file is an essential part of IEEE Std 1076.2-1996, IEEE Standard +-- VHDL Mathematical Packages. This source file may not be copied, sold, or +-- included with software that is sold without written permission from the IEEE +-- Standards Department. This source file may be used to implement this standard +-- and may be distributed in compiled form in any manner so long as the +-- compiled form does not allow direct decompilation of the original source file. +-- This source file may be copied for individual use between licensed users. +-- This source file is provided on an AS IS basis. The IEEE disclaims ANY +-- WARRANTY EXPRESS OR IMPLIED INCLUDING ANY WARRANTY OF MERCHANTABILITY +-- AND FITNESS FOR USE FOR A PARTICULAR PURPOSE. The user of the source +-- file shall indemnify and hold IEEE harmless from any damages or liability +-- arising out of the use thereof. +-- +-- Title: Standard VHDL Mathematical Packages (IEEE Std 1076.2-1996, +-- MATH_REAL) +-- +-- Library: This package shall be compiled into a library +-- symbolically named IEEE. +-- +-- Developers: IEEE DASC VHDL Mathematical Packages Working Group +-- +-- Purpose: This package defines a standard for designers to use in +-- describing VHDL models that make use of common REAL constants +-- and common REAL elementary mathematical functions. +-- +-- Limitation: The values generated by the functions in this package may +-- vary from platform to platform, and the precision of results +-- is only guaranteed to be the minimum required by IEEE Std 1076- +-- 1993. +-- +-- Notes: +-- No declarations or definitions shall be included in, or +-- excluded from, this package. +-- The "package declaration" defines the types, subtypes, and +-- declarations of MATH_REAL. +-- The standard mathematical definition and conventional meaning +-- of the mathematical functions that are part of this standard +-- represent the formal semantics of the implementation of the +-- MATH_REAL package declaration. The purpose of the MATH_REAL +-- package body is to provide a guideline for implementations to +-- verify their implementation of MATH_REAL. Tool developers may +-- choose to implement the package body in the most efficient +-- manner available to them. +-- +-- ----------------------------------------------------------------------------- +-- Version : 1.5 +-- Date : 24 July 1996 +-- ----------------------------------------------------------------------------- + +package MATH_REAL is + constant CopyRightNotice: STRING + := "Copyright 1996 IEEE. All rights reserved."; + + -- + -- Constant Definitions + -- + constant MATH_E : REAL := 2.71828_18284_59045_23536; + -- Value of e + constant MATH_1_OVER_E : REAL := 0.36787_94411_71442_32160; + -- Value of 1/e + constant MATH_PI : REAL := 3.14159_26535_89793_23846; + -- Value of pi + constant MATH_2_PI : REAL := 6.28318_53071_79586_47693; + -- Value of 2*pi + constant MATH_1_OVER_PI : REAL := 0.31830_98861_83790_67154; + -- Value of 1/pi + constant MATH_PI_OVER_2 : REAL := 1.57079_63267_94896_61923; + -- Value of pi/2 + constant MATH_PI_OVER_3 : REAL := 1.04719_75511_96597_74615; + -- Value of pi/3 + constant MATH_PI_OVER_4 : REAL := 0.78539_81633_97448_30962; + -- Value of pi/4 + constant MATH_3_PI_OVER_2 : REAL := 4.71238_89803_84689_85769; + -- Value 3*pi/2 + constant MATH_LOG_OF_2 : REAL := 0.69314_71805_59945_30942; + -- Natural log of 2 + constant MATH_LOG_OF_10 : REAL := 2.30258_50929_94045_68402; + -- Natural log of 10 + constant MATH_LOG2_OF_E : REAL := 1.44269_50408_88963_4074; + -- Log base 2 of e + constant MATH_LOG10_OF_E: REAL := 0.43429_44819_03251_82765; + -- Log base 10 of e + constant MATH_SQRT_2: REAL := 1.41421_35623_73095_04880; + -- square root of 2 + constant MATH_1_OVER_SQRT_2: REAL := 0.70710_67811_86547_52440; + -- square root of 1/2 + constant MATH_SQRT_PI: REAL := 1.77245_38509_05516_02730; + -- square root of pi + constant MATH_DEG_TO_RAD: REAL := 0.01745_32925_19943_29577; + -- Conversion factor from degree to radian + constant MATH_RAD_TO_DEG: REAL := 57.29577_95130_82320_87680; + -- Conversion factor from radian to degree + + -- + -- Function Declarations + -- + function SIGN (X: in REAL ) return REAL; + -- Purpose: + -- Returns 1.0 if X > 0.0; 0.0 if X = 0.0; -1.0 if X < 0.0 + -- Special values: + -- None + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(SIGN(X)) <= 1.0 + -- Notes: + -- None + + function CEIL (X : in REAL ) return REAL; + -- Purpose: + -- Returns smallest INTEGER value (as REAL) not less than X + -- Special values: + -- None + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- CEIL(X) is mathematically unbounded + -- Notes: + -- a) Implementations have to support at least the domain + -- ABS(X) < REAL(INTEGER'HIGH) + + function FLOOR (X : in REAL ) return REAL; + -- Purpose: + -- Returns largest INTEGER value (as REAL) not greater than X + -- Special values: + -- FLOOR(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- FLOOR(X) is mathematically unbounded + -- Notes: + -- a) Implementations have to support at least the domain + -- ABS(X) < REAL(INTEGER'HIGH) + + function ROUND (X : in REAL ) return REAL; + -- Purpose: + -- Rounds X to the nearest integer value (as real). If X is + -- halfway between two integers, rounding is away from 0.0 + -- Special values: + -- ROUND(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ROUND(X) is mathematically unbounded + -- Notes: + -- a) Implementations have to support at least the domain + -- ABS(X) < REAL(INTEGER'HIGH) + + function TRUNC (X : in REAL ) return REAL; + -- Purpose: + -- Truncates X towards 0.0 and returns truncated value + -- Special values: + -- TRUNC(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- TRUNC(X) is mathematically unbounded + -- Notes: + -- a) Implementations have to support at least the domain + -- ABS(X) < REAL(INTEGER'HIGH) + + function "MOD" (X, Y: in REAL ) return REAL; + -- Purpose: + -- Returns floating point modulus of X/Y, with the same sign as + -- Y, and absolute value less than the absolute value of Y, and + -- for some INTEGER value N the result satisfies the relation + -- X = Y*N + MOD(X,Y) + -- Special values: + -- None + -- Domain: + -- X in REAL; Y in REAL and Y /= 0.0 + -- Error conditions: + -- Error if Y = 0.0 + -- Range: + -- ABS(MOD(X,Y)) < ABS(Y) + -- Notes: + -- None + + function REALMAX (X, Y : in REAL ) return REAL; + -- Purpose: + -- Returns the algebraically larger of X and Y + -- Special values: + -- REALMAX(X,Y) = X when X = Y + -- Domain: + -- X in REAL; Y in REAL + -- Error conditions: + -- None + -- Range: + -- REALMAX(X,Y) is mathematically unbounded + -- Notes: + -- None + + function REALMIN (X, Y : in REAL ) return REAL; + -- Purpose: + -- Returns the algebraically smaller of X and Y + -- Special values: + -- REALMIN(X,Y) = X when X = Y + -- Domain: + -- X in REAL; Y in REAL + -- Error conditions: + -- None + -- Range: + -- REALMIN(X,Y) is mathematically unbounded + -- Notes: + -- None + + procedure UNIFORM(variable SEED1,SEED2:inout POSITIVE; variable X:out REAL); + -- Purpose: + -- Returns, in X, a pseudo-random number with uniform + -- distribution in the open interval (0.0, 1.0). + -- Special values: + -- None + -- Domain: + -- 1 <= SEED1 <= 2147483562; 1 <= SEED2 <= 2147483398 + -- Error conditions: + -- Error if SEED1 or SEED2 outside of valid domain + -- Range: + -- 0.0 < X < 1.0 + -- Notes: + -- a) The semantics for this function are described by the + -- algorithm published by Pierre L'Ecuyer in "Communications + -- of the ACM," vol. 31, no. 6, June 1988, pp. 742-774. + -- The algorithm is based on the combination of two + -- multiplicative linear congruential generators for 32-bit + -- platforms. + -- + -- b) Before the first call to UNIFORM, the seed values + -- (SEED1, SEED2) have to be initialized to values in the range + -- [1, 2147483562] and [1, 2147483398] respectively. The + -- seed values are modified after each call to UNIFORM. + -- + -- c) This random number generator is portable for 32-bit + -- computers, and it has a period of ~2.30584*(10**18) for each + -- set of seed values. + -- + -- d) For information on spectral tests for the algorithm, refer + -- to the L'Ecuyer article. + + function SQRT (X : in REAL ) return REAL; + -- Purpose: + -- Returns square root of X + -- Special values: + -- SQRT(0.0) = 0.0 + -- SQRT(1.0) = 1.0 + -- Domain: + -- X >= 0.0 + -- Error conditions: + -- Error if X < 0.0 + -- Range: + -- SQRT(X) >= 0.0 + -- Notes: + -- a) The upper bound of the reachable range of SQRT is + -- approximately given by: + -- SQRT(X) <= SQRT(REAL'HIGH) + + function CBRT (X : in REAL ) return REAL; + -- Purpose: + -- Returns cube root of X + -- Special values: + -- CBRT(0.0) = 0.0 + -- CBRT(1.0) = 1.0 + -- CBRT(-1.0) = -1.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- CBRT(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of CBRT is approximately given by: + -- ABS(CBRT(X)) <= CBRT(REAL'HIGH) + + function "**" (X : in INTEGER; Y : in REAL) return REAL; + -- Purpose: + -- Returns Y power of X ==> X**Y + -- Special values: + -- X**0.0 = 1.0; X /= 0 + -- 0**Y = 0.0; Y > 0.0 + -- X**1.0 = REAL(X); X >= 0 + -- 1**Y = 1.0 + -- Domain: + -- X > 0 + -- X = 0 for Y > 0.0 + -- X < 0 for Y = 0.0 + -- Error conditions: + -- Error if X < 0 and Y /= 0.0 + -- Error if X = 0 and Y <= 0.0 + -- Range: + -- X**Y >= 0.0 + -- Notes: + -- a) The upper bound of the reachable range for "**" is + -- approximately given by: + -- X**Y <= REAL'HIGH + + function "**" (X : in REAL; Y : in REAL) return REAL; + -- Purpose: + -- Returns Y power of X ==> X**Y + -- Special values: + -- X**0.0 = 1.0; X /= 0.0 + -- 0.0**Y = 0.0; Y > 0.0 + -- X**1.0 = X; X >= 0.0 + -- 1.0**Y = 1.0 + -- Domain: + -- X > 0.0 + -- X = 0.0 for Y > 0.0 + -- X < 0.0 for Y = 0.0 + -- Error conditions: + -- Error if X < 0.0 and Y /= 0.0 + -- Error if X = 0.0 and Y <= 0.0 + -- Range: + -- X**Y >= 0.0 + -- Notes: + -- a) The upper bound of the reachable range for "**" is + -- approximately given by: + -- X**Y <= REAL'HIGH + + function EXP (X : in REAL ) return REAL; + -- Purpose: + -- Returns e**X; where e = MATH_E + -- Special values: + -- EXP(0.0) = 1.0 + -- EXP(1.0) = MATH_E + -- EXP(-1.0) = MATH_1_OVER_E + -- EXP(X) = 0.0 for X <= -LOG(REAL'HIGH) + -- Domain: + -- X in REAL such that EXP(X) <= REAL'HIGH + -- Error conditions: + -- Error if X > LOG(REAL'HIGH) + -- Range: + -- EXP(X) >= 0.0 + -- Notes: + -- a) The usable domain of EXP is approximately given by: + -- X <= LOG(REAL'HIGH) + + function LOG (X : in REAL ) return REAL; + -- Purpose: + -- Returns natural logarithm of X + -- Special values: + -- LOG(1.0) = 0.0 + -- LOG(MATH_E) = 1.0 + -- Domain: + -- X > 0.0 + -- Error conditions: + -- Error if X <= 0.0 + -- Range: + -- LOG(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of LOG is approximately given by: + -- LOG(0+) <= LOG(X) <= LOG(REAL'HIGH) + + function LOG2 (X : in REAL ) return REAL; + -- Purpose: + -- Returns logarithm base 2 of X + -- Special values: + -- LOG2(1.0) = 0.0 + -- LOG2(2.0) = 1.0 + -- Domain: + -- X > 0.0 + -- Error conditions: + -- Error if X <= 0.0 + -- Range: + -- LOG2(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of LOG2 is approximately given by: + -- LOG2(0+) <= LOG2(X) <= LOG2(REAL'HIGH) + + function LOG10 (X : in REAL ) return REAL; + -- Purpose: + -- Returns logarithm base 10 of X + -- Special values: + -- LOG10(1.0) = 0.0 + -- LOG10(10.0) = 1.0 + -- Domain: + -- X > 0.0 + -- Error conditions: + -- Error if X <= 0.0 + -- Range: + -- LOG10(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of LOG10 is approximately given by: + -- LOG10(0+) <= LOG10(X) <= LOG10(REAL'HIGH) + + function LOG (X: in REAL; BASE: in REAL) return REAL; + -- Purpose: + -- Returns logarithm base BASE of X + -- Special values: + -- LOG(1.0, BASE) = 0.0 + -- LOG(BASE, BASE) = 1.0 + -- Domain: + -- X > 0.0 + -- BASE > 0.0 + -- BASE /= 1.0 + -- Error conditions: + -- Error if X <= 0.0 + -- Error if BASE <= 0.0 + -- Error if BASE = 1.0 + -- Range: + -- LOG(X, BASE) is mathematically unbounded + -- Notes: + -- a) When BASE > 1.0, the reachable range of LOG is + -- approximately given by: + -- LOG(0+, BASE) <= LOG(X, BASE) <= LOG(REAL'HIGH, BASE) + -- b) When 0.0 < BASE < 1.0, the reachable range of LOG is + -- approximately given by: + -- LOG(REAL'HIGH, BASE) <= LOG(X, BASE) <= LOG(0+, BASE) + + function SIN (X : in REAL ) return REAL; + -- Purpose: + -- Returns sine of X; X in radians + -- Special values: + -- SIN(X) = 0.0 for X = k*MATH_PI, where k is an INTEGER + -- SIN(X) = 1.0 for X = (4*k+1)*MATH_PI_OVER_2, where k is an + -- INTEGER + -- SIN(X) = -1.0 for X = (4*k+3)*MATH_PI_OVER_2, where k is an + -- INTEGER + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(SIN(X)) <= 1.0 + -- Notes: + -- a) For larger values of ABS(X), degraded accuracy is allowed. + + function COS ( X : in REAL ) return REAL; + -- Purpose: + -- Returns cosine of X; X in radians + -- Special values: + -- COS(X) = 0.0 for X = (2*k+1)*MATH_PI_OVER_2, where k is an + -- INTEGER + -- COS(X) = 1.0 for X = (2*k)*MATH_PI, where k is an INTEGER + -- COS(X) = -1.0 for X = (2*k+1)*MATH_PI, where k is an INTEGER + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(COS(X)) <= 1.0 + -- Notes: + -- a) For larger values of ABS(X), degraded accuracy is allowed. + + function TAN (X : in REAL ) return REAL; + -- Purpose: + -- Returns tangent of X; X in radians + -- Special values: + -- TAN(X) = 0.0 for X = k*MATH_PI, where k is an INTEGER + -- Domain: + -- X in REAL and + -- X /= (2*k+1)*MATH_PI_OVER_2, where k is an INTEGER + -- Error conditions: + -- Error if X = ((2*k+1) * MATH_PI_OVER_2), where k is an + -- INTEGER + -- Range: + -- TAN(X) is mathematically unbounded + -- Notes: + -- a) For larger values of ABS(X), degraded accuracy is allowed. + + function ARCSIN (X : in REAL ) return REAL; + -- Purpose: + -- Returns inverse sine of X + -- Special values: + -- ARCSIN(0.0) = 0.0 + -- ARCSIN(1.0) = MATH_PI_OVER_2 + -- ARCSIN(-1.0) = -MATH_PI_OVER_2 + -- Domain: + -- ABS(X) <= 1.0 + -- Error conditions: + -- Error if ABS(X) > 1.0 + -- Range: + -- ABS(ARCSIN(X) <= MATH_PI_OVER_2 + -- Notes: + -- None + + function ARCCOS (X : in REAL ) return REAL; + -- Purpose: + -- Returns inverse cosine of X + -- Special values: + -- ARCCOS(1.0) = 0.0 + -- ARCCOS(0.0) = MATH_PI_OVER_2 + -- ARCCOS(-1.0) = MATH_PI + -- Domain: + -- ABS(X) <= 1.0 + -- Error conditions: + -- Error if ABS(X) > 1.0 + -- Range: + -- 0.0 <= ARCCOS(X) <= MATH_PI + -- Notes: + -- None + + function ARCTAN (Y : in REAL) return REAL; + -- Purpose: + -- Returns the value of the angle in radians of the point + -- (1.0, Y), which is in rectangular coordinates + -- Special values: + -- ARCTAN(0.0) = 0.0 + -- Domain: + -- Y in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(ARCTAN(Y)) <= MATH_PI_OVER_2 + -- Notes: + -- None + + function ARCTAN (Y : in REAL; X : in REAL) return REAL; + -- Purpose: + -- Returns the principal value of the angle in radians of + -- the point (X, Y), which is in rectangular coordinates + -- Special values: + -- ARCTAN(0.0, X) = 0.0 if X > 0.0 + -- ARCTAN(0.0, X) = MATH_PI if X < 0.0 + -- ARCTAN(Y, 0.0) = MATH_PI_OVER_2 if Y > 0.0 + -- ARCTAN(Y, 0.0) = -MATH_PI_OVER_2 if Y < 0.0 + -- Domain: + -- Y in REAL + -- X in REAL, X /= 0.0 when Y = 0.0 + -- Error conditions: + -- Error if X = 0.0 and Y = 0.0 + -- Range: + -- -MATH_PI < ARCTAN(Y,X) <= MATH_PI + -- Notes: + -- None + + function SINH (X : in REAL) return REAL; + -- Purpose: + -- Returns hyperbolic sine of X + -- Special values: + -- SINH(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- SINH(X) is mathematically unbounded + -- Notes: + -- a) The usable domain of SINH is approximately given by: + -- ABS(X) <= LOG(REAL'HIGH) + + + function COSH (X : in REAL) return REAL; + -- Purpose: + -- Returns hyperbolic cosine of X + -- Special values: + -- COSH(0.0) = 1.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- COSH(X) >= 1.0 + -- Notes: + -- a) The usable domain of COSH is approximately given by: + -- ABS(X) <= LOG(REAL'HIGH) + + function TANH (X : in REAL) return REAL; + -- Purpose: + -- Returns hyperbolic tangent of X + -- Special values: + -- TANH(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ABS(TANH(X)) <= 1.0 + -- Notes: + -- None + + function ARCSINH (X : in REAL) return REAL; + -- Purpose: + -- Returns inverse hyperbolic sine of X + -- Special values: + -- ARCSINH(0.0) = 0.0 + -- Domain: + -- X in REAL + -- Error conditions: + -- None + -- Range: + -- ARCSINH(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of ARCSINH is approximately given by: + -- ABS(ARCSINH(X)) <= LOG(REAL'HIGH) + + function ARCCOSH (X : in REAL) return REAL; + -- Purpose: + -- Returns inverse hyperbolic cosine of X + -- Special values: + -- ARCCOSH(1.0) = 0.0 + -- Domain: + -- X >= 1.0 + -- Error conditions: + -- Error if X < 1.0 + -- Range: + -- ARCCOSH(X) >= 0.0 + -- Notes: + -- a) The upper bound of the reachable range of ARCCOSH is + -- approximately given by: ARCCOSH(X) <= LOG(REAL'HIGH) + + function ARCTANH (X : in REAL) return REAL; + -- Purpose: + -- Returns inverse hyperbolic tangent of X + -- Special values: + -- ARCTANH(0.0) = 0.0 + -- Domain: + -- ABS(X) < 1.0 + -- Error conditions: + -- Error if ABS(X) >= 1.0 + -- Range: + -- ARCTANH(X) is mathematically unbounded + -- Notes: + -- a) The reachable range of ARCTANH is approximately given by: + -- ABS(ARCTANH(X)) < LOG(REAL'HIGH) + +end MATH_REAL; diff --git a/lib/Standard/ieee/math_real_body.vhd b/lib/Standard/ieee/math_real_body.vhd new file mode 100644 index 0000000..c20aab7 --- /dev/null +++ b/lib/Standard/ieee/math_real_body.vhd @@ -0,0 +1,1941 @@ +------------------------------------------------------------------------ +-- +-- Copyright 1996 by IEEE. All rights reserved. + +-- This source file is an informative part of IEEE Std 1076.2-1996, IEEE Standard +-- VHDL Mathematical Packages. This source file may not be copied, sold, or +-- included with software that is sold without written permission from the IEEE +-- Standards Department. This source file may be used to implement this standard +-- and may be distributed in compiled form in any manner so long as the +-- compiled form does not allow direct decompilation of the original source file. +-- This source file may be copied for individual use between licensed users. +-- This source file is provided on an AS IS basis. The IEEE disclaims ANY +-- WARRANTY EXPRESS OR IMPLIED INCLUDING ANY WARRANTY OF MERCHANTABILITY +-- AND FITNESS FOR USE FOR A PARTICULAR PURPOSE. The user of the source +-- file shall indemnify and hold IEEE harmless from any damages or liability +-- arising out of the use thereof. + +-- +-- Title: Standard VHDL Mathematical Packages (IEEE Std 1076.2-1996, +-- MATH_REAL) +-- +-- Library: This package shall be compiled into a library +-- symbolically named IEEE. +-- +-- Developers: IEEE DASC VHDL Mathematical Packages Working Group +-- +-- Purpose: This package body is a nonnormative implementation of the +-- functionality defined in the MATH_REAL package declaration. +-- +-- Limitation: The values generated by the functions in this package may +-- vary from platform to platform, and the precision of results +-- is only guaranteed to be the minimum required by IEEE Std 1076 +-- -1993. +-- +-- Notes: +-- The "package declaration" defines the types, subtypes, and +-- declarations of MATH_REAL. +-- The standard mathematical definition and conventional meaning +-- of the mathematical functions that are part of this standard +-- represent the formal semantics of the implementation of the +-- MATH_REAL package declaration. The purpose of the MATH_REAL +-- package body is to clarify such semantics and provide a +-- guideline for implementations to verify their implementation +-- of MATH_REAL. Tool developers may choose to implement +-- the package body in the most efficient manner available to them. +-- +-- ----------------------------------------------------------------------------- +-- Version : 1.5 +-- Date : 24 July 1996 +-- ----------------------------------------------------------------------------- + +package body MATH_REAL is + + -- + -- Local Constants for Use in the Package Body Only + -- + constant MATH_E_P2 : REAL := 7.38905_60989_30650; -- e**2 + constant MATH_E_P10 : REAL := 22026.46579_48067_17; -- e**10 + constant MATH_EIGHT_PI : REAL := 25.13274_12287_18345_90770_115; --8*pi + constant MAX_ITER: INTEGER := 27; -- Maximum precision factor for cordic + constant MAX_COUNT: INTEGER := 150; -- Maximum count for number of tries + constant BASE_EPS: REAL := 0.00001; -- Factor for convergence criteria + constant KC : REAL := 6.0725293500888142e-01; -- Constant for cordic + + -- + -- Local Type Declarations for Cordic Operations + -- + type REAL_VECTOR is array (NATURAL range <>) of REAL; + type NATURAL_VECTOR is array (NATURAL range <>) of NATURAL; + subtype REAL_VECTOR_N is REAL_VECTOR (0 to MAX_ITER); + subtype REAL_ARR_2 is REAL_VECTOR (0 to 1); + subtype REAL_ARR_3 is REAL_VECTOR (0 to 2); + subtype QUADRANT is INTEGER range 0 to 3; + type CORDIC_MODE_TYPE is (ROTATION, VECTORING); + + -- + -- Auxiliary Functions for Cordic Algorithms + -- + function POWER_OF_2_SERIES (D : in NATURAL_VECTOR; INITIAL_VALUE : in REAL; + NUMBER_OF_VALUES : in NATURAL) return REAL_VECTOR is + -- Description: + -- Returns power of two for a vector of values + -- Notes: + -- None + -- + variable V : REAL_VECTOR (0 to NUMBER_OF_VALUES); + variable TEMP : REAL := INITIAL_VALUE; + variable FLAG : BOOLEAN := TRUE; + begin + for I in 0 to NUMBER_OF_VALUES loop + V(I) := TEMP; + for P in D'RANGE loop + if I = D(P) then + FLAG := FALSE; + exit; + end if; + end loop; + if FLAG then + TEMP := TEMP/2.0; + end if; + FLAG := TRUE; + end loop; + return V; + end POWER_OF_2_SERIES; + + + constant TWO_AT_MINUS : REAL_VECTOR := POWER_OF_2_SERIES( + NATURAL_VECTOR'(100, 90),1.0, + MAX_ITER); + + constant EPSILON : REAL_VECTOR_N := ( + 7.8539816339744827e-01, + 4.6364760900080606e-01, + 2.4497866312686413e-01, + 1.2435499454676144e-01, + 6.2418809995957351e-02, + 3.1239833430268277e-02, + 1.5623728620476830e-02, + 7.8123410601011116e-03, + 3.9062301319669717e-03, + 1.9531225164788189e-03, + 9.7656218955931937e-04, + 4.8828121119489829e-04, + 2.4414062014936175e-04, + 1.2207031189367021e-04, + 6.1035156174208768e-05, + 3.0517578115526093e-05, + 1.5258789061315760e-05, + 7.6293945311019699e-06, + 3.8146972656064960e-06, + 1.9073486328101870e-06, + 9.5367431640596080e-07, + 4.7683715820308876e-07, + 2.3841857910155801e-07, + 1.1920928955078067e-07, + 5.9604644775390553e-08, + 2.9802322387695303e-08, + 1.4901161193847654e-08, + 7.4505805969238281e-09 + ); + + function CORDIC ( X0 : in REAL; + Y0 : in REAL; + Z0 : in REAL; + N : in NATURAL; -- Precision factor + CORDIC_MODE : in CORDIC_MODE_TYPE -- Rotation (Z -> 0) + -- or vectoring (Y -> 0) + ) return REAL_ARR_3 is + -- Description: + -- Compute cordic values + -- Notes: + -- None + variable X : REAL := X0; + variable Y : REAL := Y0; + variable Z : REAL := Z0; + variable X_TEMP : REAL; + begin + if CORDIC_MODE = ROTATION then + for K in 0 to N loop + X_TEMP := X; + if ( Z >= 0.0) then + X := X - Y * TWO_AT_MINUS(K); + Y := Y + X_TEMP * TWO_AT_MINUS(K); + Z := Z - EPSILON(K); + else + X := X + Y * TWO_AT_MINUS(K); + Y := Y - X_TEMP * TWO_AT_MINUS(K); + Z := Z + EPSILON(K); + end if; + end loop; + else + for K in 0 to N loop + X_TEMP := X; + if ( Y < 0.0) then + X := X - Y * TWO_AT_MINUS(K); + Y := Y + X_TEMP * TWO_AT_MINUS(K); + Z := Z - EPSILON(K); + else + X := X + Y * TWO_AT_MINUS(K); + Y := Y - X_TEMP * TWO_AT_MINUS(K); + Z := Z + EPSILON(K); + end if; + end loop; + end if; + return REAL_ARR_3'(X, Y, Z); + end CORDIC; + + -- + -- Bodies for Global Mathematical Functions Start Here + -- + function SIGN (X: in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- None + begin + if ( X > 0.0 ) then + return 1.0; + elsif ( X < 0.0 ) then + return -1.0; + else + return 0.0; + end if; + end SIGN; + + function CEIL (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) No conversion to an INTEGER type is expected, so truncate + -- cannot overflow for large arguments + -- b) The domain supported by this function is X <= LARGE + -- c) Returns X if ABS(X) >= LARGE + + constant LARGE: REAL := REAL(INTEGER'HIGH); + variable RD: REAL; + + begin + if ABS(X) >= LARGE then + return X; + end if; + + RD := REAL ( INTEGER(X)); + if RD = X then + return X; + end if; + + if X > 0.0 then + if RD >= X then + return RD; + else + return RD + 1.0; + end if; + elsif X = 0.0 then + return 0.0; + else + if RD <= X then + return RD + 1.0; + else + return RD; + end if; + end if; + end CEIL; + + function FLOOR (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) No conversion to an INTEGER type is expected, so truncate + -- cannot overflow for large arguments + -- b) The domain supported by this function is ABS(X) <= LARGE + -- c) Returns X if ABS(X) >= LARGE + + constant LARGE: REAL := REAL(INTEGER'HIGH); + variable RD: REAL; + + begin + if ABS( X ) >= LARGE then + return X; + end if; + + RD := REAL ( INTEGER(X)); + if RD = X then + return X; + end if; + + if X > 0.0 then + if RD <= X then + return RD; + else + return RD - 1.0; + end if; + elsif X = 0.0 then + return 0.0; + else + if RD >= X then + return RD - 1.0; + else + return RD; + end if; + end if; + end FLOOR; + + function ROUND (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 if X = 0.0 + -- b) Returns FLOOR(X + 0.5) if X > 0 + -- c) Returns CEIL(X - 0.5) if X < 0 + + begin + if X > 0.0 then + return FLOOR(X + 0.5); + elsif X < 0.0 then + return CEIL( X - 0.5); + else + return 0.0; + end if; + end ROUND; + + function TRUNC (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 if X = 0.0 + -- b) Returns FLOOR(X) if X > 0 + -- c) Returns CEIL(X) if X < 0 + + begin + if X > 0.0 then + return FLOOR(X); + elsif X < 0.0 then + return CEIL( X); + else + return 0.0; + end if; + end TRUNC; + + + + + function "MOD" (X, Y: in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error + + variable XNEGATIVE : BOOLEAN := X < 0.0; + variable YNEGATIVE : BOOLEAN := Y < 0.0; + variable VALUE : REAL; + begin + -- Check validity of input arguments + if (Y = 0.0) then + assert FALSE + report "MOD(X, 0.0) is undefined" + severity ERROR; + return 0.0; + end if; + + -- Compute value + if ( XNEGATIVE ) then + if ( YNEGATIVE ) then + VALUE := X + (FLOOR(ABS(X)/ABS(Y)))*ABS(Y); + else + VALUE := X + (CEIL(ABS(X)/ABS(Y)))*ABS(Y); + end if; + else + if ( YNEGATIVE ) then + VALUE := X - (CEIL(ABS(X)/ABS(Y)))*ABS(Y); + else + VALUE := X - (FLOOR(ABS(X)/ABS(Y)))*ABS(Y); + end if; + end if; + + return VALUE; + end "MOD"; + + + function REALMAX (X, Y : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) REALMAX(X,Y) = X when X = Y + -- + begin + if X >= Y then + return X; + else + return Y; + end if; + end REALMAX; + + function REALMIN (X, Y : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) REALMIN(X,Y) = X when X = Y + -- + begin + if X <= Y then + return X; + else + return Y; + end if; + end REALMIN; + + + procedure UNIFORM(variable SEED1,SEED2:inout POSITIVE;variable X:out REAL) + is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error + -- + variable Z, K: INTEGER; + variable TSEED1 : INTEGER := INTEGER'(SEED1); + variable TSEED2 : INTEGER := INTEGER'(SEED2); + begin + -- Check validity of arguments + if SEED1 > 2147483562 then + assert FALSE + report "SEED1 > 2147483562 in UNIFORM" + severity ERROR; + X := 0.0; + return; + end if; + + if SEED2 > 2147483398 then + assert FALSE + report "SEED2 > 2147483398 in UNIFORM" + severity ERROR; + X := 0.0; + return; + end if; + + -- Compute new seed values and pseudo-random number + K := TSEED1/53668; + TSEED1 := 40014 * (TSEED1 - K * 53668) - K * 12211; + + if TSEED1 < 0 then + TSEED1 := TSEED1 + 2147483563; + end if; + + K := TSEED2/52774; + TSEED2 := 40692 * (TSEED2 - K * 52774) - K * 3791; + + if TSEED2 < 0 then + TSEED2 := TSEED2 + 2147483399; + end if; + + Z := TSEED1 - TSEED2; + if Z < 1 then + Z := Z + 2147483562; + end if; + + -- Get output values + SEED1 := POSITIVE'(TSEED1); + SEED2 := POSITIVE'(TSEED2); + X := REAL(Z)*4.656613e-10; + end UNIFORM; + + + + function SQRT (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Uses the Newton-Raphson approximation: + -- F(n+1) = 0.5*[F(n) + x/F(n)] + -- b) Returns 0.0 on error + -- + + constant EPS : REAL := BASE_EPS*BASE_EPS; -- Convergence factor + + variable INIVAL: REAL; + variable OLDVAL : REAL ; + variable NEWVAL : REAL ; + variable COUNT : INTEGER := 1; + + begin + -- Check validity of argument + if ( X < 0.0 ) then + assert FALSE + report "X < 0.0 in SQRT(X)" + severity ERROR; + return 0.0; + end if; + + -- Get the square root for special cases + if X = 0.0 then + return 0.0; + else + if ( X = 1.0 ) then + return 1.0; + end if; + end if; + + -- Get the square root for general cases + INIVAL := EXP(LOG(X)*(0.5)); -- Mathematically correct but imprecise + OLDVAL := INIVAL; + NEWVAL := (X/OLDVAL + OLDVAL)*0.5; + + -- Check for relative and absolute error and max count + while ( ( (ABS((NEWVAL -OLDVAL)/NEWVAL) > EPS) OR + (ABS(NEWVAL - OLDVAL) > EPS) ) AND + (COUNT < MAX_COUNT) ) loop + OLDVAL := NEWVAL; + NEWVAL := (X/OLDVAL + OLDVAL)*0.5; + COUNT := COUNT + 1; + end loop; + return NEWVAL; + end SQRT; + + function CBRT (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Uses the Newton-Raphson approximation: + -- F(n+1) = (1/3)*[2*F(n) + x/F(n)**2]; + -- + constant EPS : REAL := BASE_EPS*BASE_EPS; + + variable INIVAL: REAL; + variable XLOCAL : REAL := X; + variable NEGATIVE : BOOLEAN := X < 0.0; + variable OLDVAL : REAL ; + variable NEWVAL : REAL ; + variable COUNT : INTEGER := 1; + + begin + + -- Compute root for special cases + if X = 0.0 then + return 0.0; + elsif ( X = 1.0 ) then + return 1.0; + else + if X = -1.0 then + return -1.0; + end if; + end if; + + -- Compute root for general cases + if NEGATIVE then + XLOCAL := -X; + end if; + + INIVAL := EXP(LOG(XLOCAL)/(3.0)); -- Mathematically correct but + -- imprecise + OLDVAL := INIVAL; + NEWVAL := (XLOCAL/(OLDVAL*OLDVAL) + 2.0*OLDVAL)/3.0; + + -- Check for relative and absolute errors and max count + while ( ( (ABS((NEWVAL -OLDVAL)/NEWVAL) > EPS ) OR + (ABS(NEWVAL - OLDVAL) > EPS ) ) AND + ( COUNT < MAX_COUNT ) ) loop + OLDVAL := NEWVAL; + NEWVAL :=(XLOCAL/(OLDVAL*OLDVAL) + 2.0*OLDVAL)/3.0; + COUNT := COUNT + 1; + end loop; + + if NEGATIVE then + NEWVAL := -NEWVAL; + end if; + + return NEWVAL; + end CBRT; + + function "**" (X : in INTEGER; Y : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error condition + + begin + -- Check validity of argument + if ( ( X < 0 ) and ( Y /= 0.0 ) ) then + assert FALSE + report "X < 0 and Y /= 0.0 in X**Y" + severity ERROR; + return 0.0; + end if; + + if ( ( X = 0 ) and ( Y <= 0.0 ) ) then + assert FALSE + report "X = 0 and Y <= 0.0 in X**Y" + severity ERROR; + return 0.0; + end if; + + -- Get value for special cases + if ( X = 0 and Y > 0.0 ) then + return 0.0; + end if; + + if ( X = 1 ) then + return 1.0; + end if; + + if ( Y = 0.0 and X /= 0 ) then + return 1.0; + end if; + + if ( Y = 1.0) then + return (REAL(X)); + end if; + + -- Get value for general case + return EXP (Y * LOG (REAL(X))); + end "**"; + + function "**" (X : in REAL; Y : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error condition + + begin + -- Check validity of argument + if ( ( X < 0.0 ) and ( Y /= 0.0 ) ) then + assert FALSE + report "X < 0.0 and Y /= 0.0 in X**Y" + severity ERROR; + return 0.0; + end if; + + if ( ( X = 0.0 ) and ( Y <= 0.0 ) ) then + assert FALSE + report "X = 0.0 and Y <= 0.0 in X**Y" + severity ERROR; + return 0.0; + end if; + + -- Get value for special cases + if ( X = 0.0 and Y > 0.0 ) then + return 0.0; + end if; + + if ( X = 1.0 ) then + return 1.0; + end if; + + if ( Y = 0.0 and X /= 0.0 ) then + return 1.0; + end if; + + if ( Y = 1.0) then + return (X); + end if; + + -- Get value for general case + return EXP (Y * LOG (X)); + end "**"; + + function EXP (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) This function computes the exponential using the following + -- series: + -- exp(x) = 1 + x + x**2/2! + x**3/3! + ... ; |x| < 1.0 + -- and reduces argument X to take advantage of exp(x+y) = + -- exp(x)*exp(y) + -- + -- b) This implementation limits X to be less than LOG(REAL'HIGH) + -- to avoid overflow. Returns REAL'HIGH when X reaches that + -- limit + -- + constant EPS : REAL := BASE_EPS*BASE_EPS*BASE_EPS;-- Precision criteria + + variable RECIPROCAL: BOOLEAN := X < 0.0;-- Check sign of argument + variable XLOCAL : REAL := ABS(X); -- Use positive value + variable OLDVAL: REAL ; + variable COUNT: INTEGER ; + variable NEWVAL: REAL ; + variable LAST_TERM: REAL ; + variable FACTOR : REAL := 1.0; + + begin + -- Compute value for special cases + if X = 0.0 then + return 1.0; + end if; + + if XLOCAL = 1.0 then + if RECIPROCAL then + return MATH_1_OVER_E; + else + return MATH_E; + end if; + end if; + + if XLOCAL = 2.0 then + if RECIPROCAL then + return 1.0/MATH_E_P2; + else + return MATH_E_P2; + end if; + end if; + + if XLOCAL = 10.0 then + if RECIPROCAL then + return 1.0/MATH_E_P10; + else + return MATH_E_P10; + end if; + end if; + + if XLOCAL > LOG(REAL'HIGH) then + if RECIPROCAL then + return 0.0; + else + assert FALSE + report "X > LOG(REAL'HIGH) in EXP(X)" + severity NOTE; + return REAL'HIGH; + end if; + end if; + + -- Reduce argument to ABS(X) < 1.0 + while XLOCAL > 10.0 loop + XLOCAL := XLOCAL - 10.0; + FACTOR := FACTOR*MATH_E_P10; + end loop; + + while XLOCAL > 1.0 loop + XLOCAL := XLOCAL - 1.0; + FACTOR := FACTOR*MATH_E; + end loop; + + -- Compute value for case 0 < XLOCAL < 1 + OLDVAL := 1.0; + LAST_TERM := XLOCAL; + NEWVAL:= OLDVAL + LAST_TERM; + COUNT := 2; + + -- Check for relative and absolute errors and max count + while ( ( (ABS((NEWVAL - OLDVAL)/NEWVAL) > EPS) OR + (ABS(NEWVAL - OLDVAL) > EPS) ) AND + (COUNT < MAX_COUNT ) ) loop + OLDVAL := NEWVAL; + LAST_TERM := LAST_TERM*(XLOCAL / (REAL(COUNT))); + NEWVAL := OLDVAL + LAST_TERM; + COUNT := COUNT + 1; + end loop; + + -- Compute final value using exp(x+y) = exp(x)*exp(y) + NEWVAL := NEWVAL*FACTOR; + + if RECIPROCAL then + NEWVAL := 1.0/NEWVAL; + end if; + + return NEWVAL; + end EXP; + + + -- + -- Auxiliary Functions to Compute LOG + -- + function ILOGB(X: in REAL) return INTEGER IS + -- Description: + -- Returns n such that -1 <= ABS(X)/2^n < 2 + -- Notes: + -- None + + variable N: INTEGER := 0; + variable Y: REAL := ABS(X); + + begin + if(Y = 1.0 or Y = 0.0) then + return 0; + end if; + + if( Y > 1.0) then + while Y >= 2.0 loop + Y := Y/2.0; + N := N+1; + end loop; + return N; + end if; + + -- O < Y < 1 + while Y < 1.0 loop + Y := Y*2.0; + N := N -1; + end loop; + return N; + end ILOGB; + + function LDEXP(X: in REAL; N: in INTEGER) RETURN REAL IS + -- Description: + -- Returns X*2^n + -- Notes: + -- None + begin + return X*(2.0 ** N); + end LDEXP; + + function LOG (X : in REAL ) return REAL IS + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- + -- Notes: + -- a) Returns REAL'LOW on error + -- + -- Copyright (c) 1992 Regents of the University of California. + -- All rights reserved. + -- + -- Redistribution and use in source and binary forms, with or without + -- modification, are permitted provided that the following conditions + -- are met: + -- 1. Redistributions of source code must retain the above copyright + -- notice, this list of conditions and the following disclaimer. + -- 2. Redistributions in binary form must reproduce the above copyright + -- notice, this list of conditions and the following disclaimer in the + -- documentation and/or other materials provided with the distribution. + -- 3. All advertising materials mentioning features or use of this + -- software must display the following acknowledgement: + -- This product includes software developed by the University of + -- California, Berkeley and its contributors. + -- 4. Neither the name of the University nor the names of its + -- contributors may be used to endorse or promote products derived + -- from this software without specific prior written permission. + -- + -- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' + -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + -- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR + -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + -- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + -- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + -- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + -- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + -- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + -- DAMAGE. + -- + -- NOTE: This VHDL version was generated using the C version of the + -- original function by the IEEE VHDL Mathematical Package + -- Working Group (CS/JT) + + constant N: INTEGER := 128; + + -- Table of log(Fj) = logF_head[j] + logF_tail[j], for Fj = 1+j/128. + -- Used for generation of extend precision logarithms. + -- The constant 35184372088832 is 2^45, so the divide is exact. + -- It ensures correct reading of logF_head, even for inaccurate + -- decimal-to-binary conversion routines. (Everybody gets the + -- right answer for INTEGERs less than 2^53.) + -- Values for LOG(F) were generated using error < 10^-57 absolute + -- with the bc -l package. + + type REAL_VECTOR is array (NATURAL range <>) of REAL; + + constant A1:REAL := 0.08333333333333178827; + constant A2:REAL := 0.01250000000377174923; + constant A3:REAL := 0.002232139987919447809; + constant A4:REAL := 0.0004348877777076145742; + + constant LOGF_HEAD: REAL_VECTOR(0 TO N) := ( + 0.0, + 0.007782140442060381246, + 0.015504186535963526694, + 0.023167059281547608406, + 0.030771658666765233647, + 0.038318864302141264488, + 0.045809536031242714670, + 0.053244514518837604555, + 0.060624621816486978786, + 0.067950661908525944454, + 0.075223421237524235039, + 0.082443669210988446138, + 0.089612158689760690322, + 0.096729626458454731618, + 0.103796793681567578460, + 0.110814366340264314203, + 0.117783035656430001836, + 0.124703478501032805070, + 0.131576357788617315236, + 0.138402322859292326029, + 0.145182009844575077295, + 0.151916042025732167530, + 0.158605030176659056451, + 0.165249572895390883786, + 0.171850256926518341060, + 0.178407657472689606947, + 0.184922338493834104156, + 0.191394852999565046047, + 0.197825743329758552135, + 0.204215541428766300668, + 0.210564769107350002741, + 0.216873938300523150246, + 0.223143551314024080056, + 0.229374101064877322642, + 0.235566071312860003672, + 0.241719936886966024758, + 0.247836163904594286577, + 0.253915209980732470285, + 0.259957524436686071567, + 0.265963548496984003577, + 0.271933715484010463114, + 0.277868451003087102435, + 0.283768173130738432519, + 0.289633292582948342896, + 0.295464212893421063199, + 0.301261330578199704177, + 0.307025035294827830512, + 0.312755710004239517729, + 0.318453731118097493890, + 0.324119468654316733591, + 0.329753286372579168528, + 0.335355541920762334484, + 0.340926586970454081892, + 0.346466767346100823488, + 0.351976423156884266063, + 0.357455888922231679316, + 0.362905493689140712376, + 0.368325561158599157352, + 0.373716409793814818840, + 0.379078352934811846353, + 0.384411698910298582632, + 0.389716751140440464951, + 0.394993808240542421117, + 0.400243164127459749579, + 0.405465108107819105498, + 0.410659924985338875558, + 0.415827895143593195825, + 0.420969294644237379543, + 0.426084395310681429691, + 0.431173464818130014464, + 0.436236766774527495726, + 0.441274560805140936281, + 0.446287102628048160113, + 0.451274644139630254358, + 0.456237433481874177232, + 0.461175715122408291790, + 0.466089729924533457960, + 0.470979715219073113985, + 0.475845904869856894947, + 0.480688529345570714212, + 0.485507815781602403149, + 0.490303988045525329653, + 0.495077266798034543171, + 0.499827869556611403822, + 0.504556010751912253908, + 0.509261901790523552335, + 0.513945751101346104405, + 0.518607764208354637958, + 0.523248143765158602036, + 0.527867089620485785417, + 0.532464798869114019908, + 0.537041465897345915436, + 0.541597282432121573947, + 0.546132437597407260909, + 0.550647117952394182793, + 0.555141507540611200965, + 0.559615787935399566777, + 0.564070138285387656651, + 0.568504735352689749561, + 0.572919753562018740922, + 0.577315365035246941260, + 0.581691739635061821900, + 0.586049045003164792433, + 0.590387446602107957005, + 0.594707107746216934174, + 0.599008189645246602594, + 0.603290851438941899687, + 0.607555250224322662688, + 0.611801541106615331955, + 0.616029877215623855590, + 0.620240409751204424537, + 0.624433288012369303032, + 0.628608659422752680256, + 0.632766669570628437213, + 0.636907462236194987781, + 0.641031179420679109171, + 0.645137961373620782978, + 0.649227946625615004450, + 0.653301272011958644725, + 0.657358072709030238911, + 0.661398482245203922502, + 0.665422632544505177065, + 0.669430653942981734871, + 0.673422675212350441142, + 0.677398823590920073911, + 0.681359224807238206267, + 0.685304003098281100392, + 0.689233281238557538017, + 0.693147180560117703862); + + constant LOGF_TAIL: REAL_VECTOR(0 TO N) := ( + 0.0, + -0.00000000000000543229938420049, + 0.00000000000000172745674997061, + -0.00000000000001323017818229233, + -0.00000000000001154527628289872, + -0.00000000000000466529469958300, + 0.00000000000005148849572685810, + -0.00000000000002532168943117445, + -0.00000000000005213620639136504, + -0.00000000000001819506003016881, + 0.00000000000006329065958724544, + 0.00000000000008614512936087814, + -0.00000000000007355770219435028, + 0.00000000000009638067658552277, + 0.00000000000007598636597194141, + 0.00000000000002579999128306990, + -0.00000000000004654729747598444, + -0.00000000000007556920687451336, + 0.00000000000010195735223708472, + -0.00000000000017319034406422306, + -0.00000000000007718001336828098, + 0.00000000000010980754099855238, + -0.00000000000002047235780046195, + -0.00000000000008372091099235912, + 0.00000000000014088127937111135, + 0.00000000000012869017157588257, + 0.00000000000017788850778198106, + 0.00000000000006440856150696891, + 0.00000000000016132822667240822, + -0.00000000000007540916511956188, + -0.00000000000000036507188831790, + 0.00000000000009120937249914984, + 0.00000000000018567570959796010, + -0.00000000000003149265065191483, + -0.00000000000009309459495196889, + 0.00000000000017914338601329117, + -0.00000000000001302979717330866, + 0.00000000000023097385217586939, + 0.00000000000023999540484211737, + 0.00000000000015393776174455408, + -0.00000000000036870428315837678, + 0.00000000000036920375082080089, + -0.00000000000009383417223663699, + 0.00000000000009433398189512690, + 0.00000000000041481318704258568, + -0.00000000000003792316480209314, + 0.00000000000008403156304792424, + -0.00000000000034262934348285429, + 0.00000000000043712191957429145, + -0.00000000000010475750058776541, + -0.00000000000011118671389559323, + 0.00000000000037549577257259853, + 0.00000000000013912841212197565, + 0.00000000000010775743037572640, + 0.00000000000029391859187648000, + -0.00000000000042790509060060774, + 0.00000000000022774076114039555, + 0.00000000000010849569622967912, + -0.00000000000023073801945705758, + 0.00000000000015761203773969435, + 0.00000000000003345710269544082, + -0.00000000000041525158063436123, + 0.00000000000032655698896907146, + -0.00000000000044704265010452446, + 0.00000000000034527647952039772, + -0.00000000000007048962392109746, + 0.00000000000011776978751369214, + -0.00000000000010774341461609578, + 0.00000000000021863343293215910, + 0.00000000000024132639491333131, + 0.00000000000039057462209830700, + -0.00000000000026570679203560751, + 0.00000000000037135141919592021, + -0.00000000000017166921336082431, + -0.00000000000028658285157914353, + -0.00000000000023812542263446809, + 0.00000000000006576659768580062, + -0.00000000000028210143846181267, + 0.00000000000010701931762114254, + 0.00000000000018119346366441110, + 0.00000000000009840465278232627, + -0.00000000000033149150282752542, + -0.00000000000018302857356041668, + -0.00000000000016207400156744949, + 0.00000000000048303314949553201, + -0.00000000000071560553172382115, + 0.00000000000088821239518571855, + -0.00000000000030900580513238244, + -0.00000000000061076551972851496, + 0.00000000000035659969663347830, + 0.00000000000035782396591276383, + -0.00000000000046226087001544578, + 0.00000000000062279762917225156, + 0.00000000000072838947272065741, + 0.00000000000026809646615211673, + -0.00000000000010960825046059278, + 0.00000000000002311949383800537, + -0.00000000000058469058005299247, + -0.00000000000002103748251144494, + -0.00000000000023323182945587408, + -0.00000000000042333694288141916, + -0.00000000000043933937969737844, + 0.00000000000041341647073835565, + 0.00000000000006841763641591466, + 0.00000000000047585534004430641, + 0.00000000000083679678674757695, + -0.00000000000085763734646658640, + 0.00000000000021913281229340092, + -0.00000000000062242842536431148, + -0.00000000000010983594325438430, + 0.00000000000065310431377633651, + -0.00000000000047580199021710769, + -0.00000000000037854251265457040, + 0.00000000000040939233218678664, + 0.00000000000087424383914858291, + 0.00000000000025218188456842882, + -0.00000000000003608131360422557, + -0.00000000000050518555924280902, + 0.00000000000078699403323355317, + -0.00000000000067020876961949060, + 0.00000000000016108575753932458, + 0.00000000000058527188436251509, + -0.00000000000035246757297904791, + -0.00000000000018372084495629058, + 0.00000000000088606689813494916, + 0.00000000000066486268071468700, + 0.00000000000063831615170646519, + 0.00000000000025144230728376072, + -0.00000000000017239444525614834); + + variable M, J:INTEGER; + variable F1, F2, G, Q, U, U2, V: REAL; + variable ZERO: REAL := 0.0;--Made variable so no constant folding occurs + variable ONE: REAL := 1.0; --Made variable so no constant folding occurs + + -- double logb(), ldexp(); + + variable U1:REAL; + + begin + + -- Check validity of argument + if ( X <= 0.0 ) then + assert FALSE + report "X <= 0.0 in LOG(X)" + severity ERROR; + return(REAL'LOW); + end if; + + -- Compute value for special cases + if ( X = 1.0 ) then + return 0.0; + end if; + + if ( X = MATH_E ) then + return 1.0; + end if; + + -- Argument reduction: 1 <= g < 2; x/2^m = g; + -- y = F*(1 + f/F) for |f| <= 2^-8 + + M := ILOGB(X); + G := LDEXP(X, -M); + J := INTEGER(REAL(N)*(G-1.0)); -- C code adds 0.5 for rounding + F1 := (1.0/REAL(N)) * REAL(J) + 1.0; --F1*128 is an INTEGER in [128,512] + F2 := G - F1; + + -- Approximate expansion for log(1+f2/F1) ~= u + q + G := 1.0/(2.0*F1+F2); + U := 2.0*F2*G; + V := U*U; + Q := U*V*(A1 + V*(A2 + V*(A3 + V*A4))); + + -- Case 1: u1 = u rounded to 2^-43 absolute. Since u < 2^-8, + -- u1 has at most 35 bits, and F1*u1 is exact, as F1 has < 8 bits. + -- It also adds exactly to |m*log2_hi + log_F_head[j] | < 750. + -- + if ( J /= 0 or M /= 0) then + U1 := U + 513.0; + U1 := U1 - 513.0; + + -- Case 2: |1-x| < 1/256. The m- and j- dependent terms are zero + -- u1 = u to 24 bits. + -- + else + U1 := U; + --TRUNC(U1); --In c this is u1 = (double) (float) (u1) + end if; + + U2 := (2.0*(F2 - F1*U1) - U1*F2) * G; + -- u1 + u2 = 2f/(2F+f) to extra precision. + + -- log(x) = log(2^m*F1*(1+f2/F1)) = + -- (m*log2_hi+LOGF_HEAD(j)+u1) + (m*log2_lo+LOGF_TAIL(j)+q); + -- (exact) + (tiny) + + U1 := U1 + REAL(M)*LOGF_HEAD(N) + LOGF_HEAD(J); -- Exact + U2 := (U2 + LOGF_TAIL(J)) + Q; -- Tiny + U2 := U2 + LOGF_TAIL(N)*REAL(M); + return (U1 + U2); + end LOG; + + + function LOG2 (X: in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns REAL'LOW on error + begin + -- Check validity of arguments + if ( X <= 0.0 ) then + assert FALSE + report "X <= 0.0 in LOG2(X)" + severity ERROR; + return(REAL'LOW); + end if; + + -- Compute value for special cases + if ( X = 1.0 ) then + return 0.0; + end if; + + if ( X = 2.0 ) then + return 1.0; + end if; + + -- Compute value for general case + return ( MATH_LOG2_OF_E*LOG(X) ); + end LOG2; + + + function LOG10 (X: in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns REAL'LOW on error + begin + -- Check validity of arguments + if ( X <= 0.0 ) then + assert FALSE + report "X <= 0.0 in LOG10(X)" + severity ERROR; + return(REAL'LOW); + end if; + + -- Compute value for special cases + if ( X = 1.0 ) then + return 0.0; + end if; + + if ( X = 10.0 ) then + return 1.0; + end if; + + -- Compute value for general case + return ( MATH_LOG10_OF_E*LOG(X) ); + end LOG10; + + + function LOG (X: in REAL; BASE: in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns REAL'LOW on error + begin + -- Check validity of arguments + if ( X <= 0.0 ) then + assert FALSE + report "X <= 0.0 in LOG(X, BASE)" + severity ERROR; + return(REAL'LOW); + end if; + + if ( BASE <= 0.0 or BASE = 1.0 ) then + assert FALSE + report "BASE <= 0.0 or BASE = 1.0 in LOG(X, BASE)" + severity ERROR; + return(REAL'LOW); + end if; + + -- Compute value for special cases + if ( X = 1.0 ) then + return 0.0; + end if; + + if ( X = BASE ) then + return 1.0; + end if; + + -- Compute value for general case + return ( LOG(X)/LOG(BASE)); + end LOG; + + + function SIN (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) SIN(-X) = -SIN(X) + -- b) SIN(X) = X if ABS(X) < EPS + -- c) SIN(X) = X - X**3/3! if EPS < ABS(X) < BASE_EPS + -- d) SIN(MATH_PI_OVER_2 - X) = COS(X) + -- e) COS(X) = 1.0 - 0.5*X**2 if ABS(X) < EPS + -- f) COS(X) = 1.0 - 0.5*X**2 + (X**4)/4! if + -- EPS< ABS(X) MATH_2_PI then + TEMP := FLOOR(XLOCAL/MATH_2_PI); + XLOCAL := XLOCAL - TEMP*MATH_2_PI; + end if; + + if XLOCAL < 0.0 then + assert FALSE + report "XLOCAL <= 0.0 after reduction in SIN(X)" + severity ERROR; + XLOCAL := -XLOCAL; + end if; + + -- Compute value for special cases + if XLOCAL = 0.0 or XLOCAL = MATH_2_PI or XLOCAL = MATH_PI then + return 0.0; + end if; + + if XLOCAL = MATH_PI_OVER_2 then + if NEGATIVE then + return -1.0; + else + return 1.0; + end if; + end if; + + if XLOCAL = MATH_3_PI_OVER_2 then + if NEGATIVE then + return 1.0; + else + return -1.0; + end if; + end if; + + if XLOCAL < EPS then + if NEGATIVE then + return -XLOCAL; + else + return XLOCAL; + end if; + else + if XLOCAL < BASE_EPS then + TEMP := XLOCAL - (XLOCAL*XLOCAL*XLOCAL)/6.0; + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + end if; + end if; + + TEMP := MATH_PI - XLOCAL; + if ABS(TEMP) < EPS then + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + else + if ABS(TEMP) < BASE_EPS then + TEMP := TEMP - (TEMP*TEMP*TEMP)/6.0; + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + end if; + end if; + + TEMP := MATH_2_PI - XLOCAL; + if ABS(TEMP) < EPS then + if NEGATIVE then + return TEMP; + else + return -TEMP; + end if; + else + if ABS(TEMP) < BASE_EPS then + TEMP := TEMP - (TEMP*TEMP*TEMP)/6.0; + if NEGATIVE then + return TEMP; + else + return -TEMP; + end if; + end if; + end if; + + TEMP := ABS(MATH_PI_OVER_2 - XLOCAL); + if TEMP < EPS then + TEMP := 1.0 - TEMP*TEMP*0.5; + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + else + if TEMP < BASE_EPS then + TEMP := 1.0 -TEMP*TEMP*0.5 + TEMP*TEMP*TEMP*TEMP/24.0; + if NEGATIVE then + return -TEMP; + else + return TEMP; + end if; + end if; + end if; + + TEMP := ABS(MATH_3_PI_OVER_2 - XLOCAL); + if TEMP < EPS then + TEMP := 1.0 - TEMP*TEMP*0.5; + if NEGATIVE then + return TEMP; + else + return -TEMP; + end if; + else + if TEMP < BASE_EPS then + TEMP := 1.0 -TEMP*TEMP*0.5 + TEMP*TEMP*TEMP*TEMP/24.0; + if NEGATIVE then + return TEMP; + else + return -TEMP; + end if; + end if; + end if; + + -- Compute value for general cases + if ((XLOCAL < MATH_PI_OVER_2 ) and (XLOCAL > 0.0)) then + VALUE:= CORDIC( KC, 0.0, x, 27, ROTATION)(1); + end if; + + N := INTEGER ( FLOOR(XLOCAL/MATH_PI_OVER_2)); + case QUADRANT( N mod 4) is + when 0 => + VALUE := CORDIC( KC, 0.0, XLOCAL, 27, ROTATION)(1); + when 1 => + VALUE := CORDIC( KC, 0.0, XLOCAL - MATH_PI_OVER_2, 27, + ROTATION)(0); + when 2 => + VALUE := -CORDIC( KC, 0.0, XLOCAL - MATH_PI, 27, ROTATION)(1); + when 3 => + VALUE := -CORDIC( KC, 0.0, XLOCAL - MATH_3_PI_OVER_2, 27, + ROTATION)(0); + end case; + + if NEGATIVE then + return -VALUE; + else + return VALUE; + end if; + end SIN; + + + function COS (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) COS(-X) = COS(X) + -- b) COS(X) = SIN(MATH_PI_OVER_2 - X) + -- c) COS(MATH_PI + X) = -COS(X) + -- d) COS(X) = 1.0 - X*X/2.0 if ABS(X) < EPS + -- e) COS(X) = 1.0 - 0.5*X**2 + (X**4)/4! if + -- EPS< ABS(X) MATH_2_PI then + TEMP := FLOOR(XLOCAL/MATH_2_PI); + XLOCAL := XLOCAL - TEMP*MATH_2_PI; + end if; + + if XLOCAL < 0.0 then + assert FALSE + report "XLOCAL <= 0.0 after reduction in COS(X)" + severity ERROR; + XLOCAL := -XLOCAL; + end if; + + -- Compute value for special cases + if XLOCAL = 0.0 or XLOCAL = MATH_2_PI then + return 1.0; + end if; + + if XLOCAL = MATH_PI then + return -1.0; + end if; + + if XLOCAL = MATH_PI_OVER_2 or XLOCAL = MATH_3_PI_OVER_2 then + return 0.0; + end if; + + TEMP := ABS(XLOCAL); + if ( TEMP < EPS) then + return (1.0 - 0.5*TEMP*TEMP); + else + if (TEMP < BASE_EPS) then + return (1.0 -0.5*TEMP*TEMP + TEMP*TEMP*TEMP*TEMP/24.0); + end if; + end if; + + TEMP := ABS(XLOCAL -MATH_2_PI); + if ( TEMP < EPS) then + return (1.0 - 0.5*TEMP*TEMP); + else + if (TEMP < BASE_EPS) then + return (1.0 -0.5*TEMP*TEMP + TEMP*TEMP*TEMP*TEMP/24.0); + end if; + end if; + + TEMP := ABS (XLOCAL - MATH_PI); + if TEMP < EPS then + return (-1.0 + 0.5*TEMP*TEMP); + else + if (TEMP < BASE_EPS) then + return (-1.0 +0.5*TEMP*TEMP - TEMP*TEMP*TEMP*TEMP/24.0); + end if; + end if; + + -- Compute value for general cases + return SIN(MATH_PI_OVER_2 - XLOCAL); + end COS; + + function TAN (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) TAN(0.0) = 0.0 + -- b) TAN(-X) = -TAN(X) + -- c) Returns REAL'LOW on error if X < 0.0 + -- d) Returns REAL'HIGH on error if X > 0.0 + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X) ; + variable VALUE: REAL; + variable TEMP : REAL; + + begin + -- Make 0.0 <= XLOCAL <= MATH_2_PI + if XLOCAL > MATH_2_PI then + TEMP := FLOOR(XLOCAL/MATH_2_PI); + XLOCAL := XLOCAL - TEMP*MATH_2_PI; + end if; + + if XLOCAL < 0.0 then + assert FALSE + report "XLOCAL <= 0.0 after reduction in TAN(X)" + severity ERROR; + XLOCAL := -XLOCAL; + end if; + + -- Check validity of argument + if XLOCAL = MATH_PI_OVER_2 then + assert FALSE + report "X is a multiple of MATH_PI_OVER_2 in TAN(X)" + severity ERROR; + if NEGATIVE then + return(REAL'LOW); + else + return(REAL'HIGH); + end if; + end if; + + if XLOCAL = MATH_3_PI_OVER_2 then + assert FALSE + report "X is a multiple of MATH_3_PI_OVER_2 in TAN(X)" + severity ERROR; + if NEGATIVE then + return(REAL'HIGH); + else + return(REAL'LOW); + end if; + end if; + + -- Compute value for special cases + if XLOCAL = 0.0 or XLOCAL = MATH_PI then + return 0.0; + end if; + + -- Compute value for general cases + VALUE := SIN(XLOCAL)/COS(XLOCAL); + if NEGATIVE then + return -VALUE; + else + return VALUE; + end if; + end TAN; + + function ARCSIN (X : in REAL ) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ARCSIN(-X) = -ARCSIN(X) + -- b) Returns X on error + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X); + variable VALUE : REAL; + + begin + -- Check validity of arguments + if XLOCAL > 1.0 then + assert FALSE + report "ABS(X) > 1.0 in ARCSIN(X)" + severity ERROR; + return X; + end if; + + -- Compute value for special cases + if XLOCAL = 0.0 then + return 0.0; + elsif XLOCAL = 1.0 then + if NEGATIVE then + return -MATH_PI_OVER_2; + else + return MATH_PI_OVER_2; + end if; + end if; + + -- Compute value for general cases + if XLOCAL < 0.9 then + VALUE := ARCTAN(XLOCAL/(SQRT(1.0 - XLOCAL*XLOCAL))); + else + VALUE := MATH_PI_OVER_2 - ARCTAN(SQRT(1.0 - XLOCAL*XLOCAL)/XLOCAL); + end if; + + if NEGATIVE then + VALUE := -VALUE; + end if; + + return VALUE; + end ARCSIN; + + function ARCCOS (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ARCCOS(-X) = MATH_PI - ARCCOS(X) + -- b) Returns X on error + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X); + variable VALUE : REAL; + + begin + -- Check validity of argument + if XLOCAL > 1.0 then + assert FALSE + report "ABS(X) > 1.0 in ARCCOS(X)" + severity ERROR; + return X; + end if; + + -- Compute value for special cases + if X = 1.0 then + return 0.0; + elsif X = 0.0 then + return MATH_PI_OVER_2; + elsif X = -1.0 then + return MATH_PI; + end if; + + -- Compute value for general cases + if XLOCAL > 0.9 then + VALUE := ARCTAN(SQRT(1.0 - XLOCAL*XLOCAL)/XLOCAL); + else + VALUE := MATH_PI_OVER_2 - ARCTAN(XLOCAL/SQRT(1.0 - XLOCAL*XLOCAL)); + end if; + + + if NEGATIVE then + VALUE := MATH_PI - VALUE; + end if; + + return VALUE; + end ARCCOS; + + + function ARCTAN (Y : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) ARCTAN(-Y) = -ARCTAN(Y) + -- b) ARCTAN(Y) = -ARCTAN(1.0/Y) + MATH_PI_OVER_2 for |Y| > 1.0 + -- c) ARCTAN(Y) = Y for |Y| < EPS + + constant EPS : REAL := BASE_EPS*BASE_EPS*BASE_EPS; + + variable NEGATIVE : BOOLEAN := Y < 0.0; + variable RECIPROCAL : BOOLEAN; + variable YLOCAL : REAL := ABS(Y); + variable VALUE : REAL; + + begin + -- Make argument |Y| <=1.0 + if YLOCAL > 1.0 then + YLOCAL := 1.0/YLOCAL; + RECIPROCAL := TRUE; + else + RECIPROCAL := FALSE; + end if; + + -- Compute value for special cases + if YLOCAL = 0.0 then + if RECIPROCAL then + if NEGATIVE then + return (-MATH_PI_OVER_2); + else + return (MATH_PI_OVER_2); + end if; + else + return 0.0; + end if; + end if; + + if YLOCAL < EPS then + if NEGATIVE then + if RECIPROCAL then + return (-MATH_PI_OVER_2 + YLOCAL); + else + return -YLOCAL; + end if; + else + if RECIPROCAL then + return (MATH_PI_OVER_2 - YLOCAL); + else + return YLOCAL; + end if; + end if; + end if; + + -- Compute value for general cases + VALUE := CORDIC( 1.0, YLOCAL, 0.0, 27, VECTORING )(2); + + if RECIPROCAL then + VALUE := MATH_PI_OVER_2 - VALUE; + end if; + + if NEGATIVE then + VALUE := -VALUE; + end if; + + return VALUE; + end ARCTAN; + + + function ARCTAN (Y : in REAL; X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns 0.0 on error + + variable YLOCAL : REAL; + variable VALUE : REAL; + begin + + -- Check validity of arguments + if (Y = 0.0 and X = 0.0 ) then + assert FALSE report + "ARCTAN(0.0, 0.0) is undetermined" + severity ERROR; + return 0.0; + end if; + + -- Compute value for special cases + if Y = 0.0 then + if X > 0.0 then + return 0.0; + else + return MATH_PI; + end if; + end if; + + if X = 0.0 then + if Y > 0.0 then + return MATH_PI_OVER_2; + else + return -MATH_PI_OVER_2; + end if; + end if; + + + -- Compute value for general cases + YLOCAL := ABS(Y/X); + + VALUE := ARCTAN(YLOCAL); + + if X < 0.0 then + VALUE := MATH_PI - VALUE; + end if; + + if Y < 0.0 then + VALUE := -VALUE; + end if; + + return VALUE; + end ARCTAN; + + + function SINH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (EXP(X) - EXP(-X))/2.0 + -- b) SINH(-X) = SINH(X) + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X); + variable TEMP : REAL; + variable VALUE : REAL; + + begin + -- Compute value for special cases + if XLOCAL = 0.0 then + return 0.0; + end if; + + -- Compute value for general cases + TEMP := EXP(XLOCAL); + VALUE := (TEMP - 1.0/TEMP)*0.5; + + if NEGATIVE then + VALUE := -VALUE; + end if; + + return VALUE; + end SINH; + + function COSH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (EXP(X) + EXP(-X))/2.0 + -- b) COSH(-X) = COSH(X) + + variable XLOCAL : REAL := ABS(X); + variable TEMP : REAL; + variable VALUE : REAL; + begin + -- Compute value for special cases + if XLOCAL = 0.0 then + return 1.0; + end if; + + + -- Compute value for general cases + TEMP := EXP(XLOCAL); + VALUE := (TEMP + 1.0/TEMP)*0.5; + + return VALUE; + end COSH; + + function TANH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (EXP(X) - EXP(-X))/(EXP(X) + EXP(-X)) + -- b) TANH(-X) = -TANH(X) + + variable NEGATIVE : BOOLEAN := X < 0.0; + variable XLOCAL : REAL := ABS(X); + variable TEMP : REAL; + variable VALUE : REAL; + + begin + -- Compute value for special cases + if XLOCAL = 0.0 then + return 0.0; + end if; + + -- Compute value for general cases + TEMP := EXP(XLOCAL); + VALUE := (TEMP - 1.0/TEMP)/(TEMP + 1.0/TEMP); + + if NEGATIVE then + return -VALUE; + else + return VALUE; + end if; + end TANH; + + function ARCSINH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns LOG( X + SQRT( X*X + 1.0)) + + begin + -- Compute value for special cases + if X = 0.0 then + return 0.0; + end if; + + -- Compute value for general cases + return ( LOG( X + SQRT( X*X + 1.0)) ); + end ARCSINH; + + + + function ARCCOSH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns LOG( X + SQRT( X*X - 1.0)); X >= 1.0 + -- b) Returns X on error + + begin + -- Check validity of arguments + if X < 1.0 then + assert FALSE + report "X < 1.0 in ARCCOSH(X)" + severity ERROR; + return X; + end if; + + -- Compute value for special cases + if X = 1.0 then + return 0.0; + end if; + + -- Compute value for general cases + return ( LOG( X + SQRT( X*X - 1.0))); + end ARCCOSH; + + function ARCTANH (X : in REAL) return REAL is + -- Description: + -- See function declaration in IEEE Std 1076.2-1996 + -- Notes: + -- a) Returns (LOG( (1.0 + X)/(1.0 - X)))/2.0 ; | X | < 1.0 + -- b) Returns X on error + begin + -- Check validity of arguments + if ABS(X) >= 1.0 then + assert FALSE + report "ABS(X) >= 1.0 in ARCTANH(X)" + severity ERROR; + return X; + end if; + + -- Compute value for special cases + if X = 0.0 then + return 0.0; + end if; + + -- Compute value for general cases + return( 0.5*LOG( (1.0+X)/(1.0-X) ) ); + end ARCTANH; + +end MATH_REAL; diff --git a/lib/Standard/ieee/new/math_complex.vhdl b/lib/Standard/ieee/new/math_complex.vhdl new file mode 100644 index 0000000..2f9376b --- /dev/null +++ b/lib/Standard/ieee/new/math_complex.vhdl @@ -0,0 +1,126 @@ +--------------------------------------------------------------- +-- +-- This source file may be used and distributed without restriction. +-- No declarations or definitions shall be included in this package. +-- This package cannot be sold or distributed for profit. +-- +-- **************************************************************** +-- * * +-- * W A R N I N G * +-- * * +-- * This DRAFT version IS NOT endorsed or approved by IEEE * +-- * * +-- **************************************************************** +-- +-- Title: PACKAGE MATH_COMPLEX +-- +-- Purpose: VHDL declarations for mathematical package MATH_COMPLEX +-- which contains common complex constants and basic complex +-- functions and operations. +-- +-- Author: IEEE VHDL Math Package Study Group +-- +-- Notes: +-- The package body uses package IEEE.MATH_REAL +-- +-- The package body shall be considered the formal definition of +-- the semantics of this package. Tool developers may choose to implement +-- the package body in the most efficient manner available to them. +-- +-- History: +-- Version 0.1 (Strawman) Jose A. Torres 6/22/92 +-- Version 0.2 Jose A. Torres 1/15/93 +-- Version 0.3 Jose A. Torres 4/13/93 +-- Version 0.4 Jose A. Torres 4/19/93 +-- Version 0.5 Jose A. Torres 4/20/93 +-- Version 0.6 Jose A. Torres 4/23/93 Added unary minus +-- and CONJ for polar +-- Version 0.7 Jose A. Torres 5/28/93 Rev up for compatibility +-- with package body. +------------------------------------------------------------- +Library IEEE; + +Package MATH_COMPLEX is + + + type COMPLEX is record RE, IM: real; end record; + type COMPLEX_VECTOR is array (integer range <>) of COMPLEX; + type COMPLEX_POLAR is record MAG: real; ARG: real; end record; + + constant CBASE_1: complex := COMPLEX'(1.0, 0.0); + constant CBASE_j: complex := COMPLEX'(0.0, 1.0); + constant CZERO: complex := COMPLEX'(0.0, 0.0); + + function CABS(Z: in complex ) return real; + -- returns absolute value (magnitude) of Z + + function CARG(Z: in complex ) return real; + -- returns argument (angle) in radians of a complex number + + function CMPLX(X: in real; Y: in real:= 0.0 ) return complex; + -- returns complex number X + iY + + function "-" (Z: in complex ) return complex; + -- unary minus + + function "-" (Z: in complex_polar ) return complex_polar; + -- unary minus + + function CONJ (Z: in complex) return complex; + -- returns complex conjugate + + function CONJ (Z: in complex_polar) return complex_polar; + -- returns complex conjugate + + function CSQRT(Z: in complex ) return complex_vector; + -- returns square root of Z; 2 values + + function CEXP(Z: in complex ) return complex; + -- returns e**Z + + function COMPLEX_TO_POLAR(Z: in complex ) return complex_polar; + -- converts complex to complex_polar + + function POLAR_TO_COMPLEX(Z: in complex_polar ) return complex; + -- converts complex_polar to complex + + + -- arithmetic operators + + function "+" ( L: in complex; R: in complex ) return complex; + function "+" ( L: in complex_polar; R: in complex_polar) return complex; + function "+" ( L: in complex_polar; R: in complex ) return complex; + function "+" ( L: in complex; R: in complex_polar) return complex; + function "+" ( L: in real; R: in complex ) return complex; + function "+" ( L: in complex; R: in real ) return complex; + function "+" ( L: in real; R: in complex_polar) return complex; + function "+" ( L: in complex_polar; R: in real) return complex; + + function "-" ( L: in complex; R: in complex ) return complex; + function "-" ( L: in complex_polar; R: in complex_polar) return complex; + function "-" ( L: in complex_polar; R: in complex ) return complex; + function "-" ( L: in complex; R: in complex_polar) return complex; + function "-" ( L: in real; R: in complex ) return complex; + function "-" ( L: in complex; R: in real ) return complex; + function "-" ( L: in real; R: in complex_polar) return complex; + function "-" ( L: in complex_polar; R: in real) return complex; + + function "*" ( L: in complex; R: in complex ) return complex; + function "*" ( L: in complex_polar; R: in complex_polar) return complex; + function "*" ( L: in complex_polar; R: in complex ) return complex; + function "*" ( L: in complex; R: in complex_polar) return complex; + function "*" ( L: in real; R: in complex ) return complex; + function "*" ( L: in complex; R: in real ) return complex; + function "*" ( L: in real; R: in complex_polar) return complex; + function "*" ( L: in complex_polar; R: in real) return complex; + + + function "/" ( L: in complex; R: in complex ) return complex; + function "/" ( L: in complex_polar; R: in complex_polar) return complex; + function "/" ( L: in complex_polar; R: in complex ) return complex; + function "/" ( L: in complex; R: in complex_polar) return complex; + function "/" ( L: in real; R: in complex ) return complex; + function "/" ( L: in complex; R: in real ) return complex; + function "/" ( L: in real; R: in complex_polar) return complex; + function "/" ( L: in complex_polar; R: in real) return complex; +end MATH_COMPLEX; diff --git a/lib/Standard/ieee/new/math_real.vhdl b/lib/Standard/ieee/new/math_real.vhdl new file mode 100644 index 0000000..0ad3abe --- /dev/null +++ b/lib/Standard/ieee/new/math_real.vhdl @@ -0,0 +1,211 @@ +------------------------------------------------------------------------ +-- +-- This source file may be used and distributed without restriction. +-- No declarations or definitions shall be added to this package. +-- This package cannot be sold or distributed for profit. +-- +-- **************************************************************** +-- * * +-- * W A R N I N G * +-- * * +-- * This DRAFT version IS NOT endorsed or approved by IEEE * +-- * * +-- **************************************************************** +-- +-- Title: PACKAGE MATH_REAL +-- +-- Library: This package shall be compiled into a library +-- symbolically named IEEE. +-- +-- Purpose: VHDL declarations for mathematical package MATH_REAL +-- which contains common real constants, common real +-- functions, and real trascendental functions. +-- +-- Author: IEEE VHDL Math Package Study Group +-- +-- Notes: +-- The package body shall be considered the formal definition of +-- the semantics of this package. Tool developers may choose to implement +-- the package body in the most efficient manner available to them. +-- +-- History: +-- Version 0.1 (Strawman) Jose A. Torres 6/22/92 +-- Version 0.2 Jose A. Torres 1/15/93 +-- Version 0.3 Jose A. Torres 4/13/93 +-- Version 0.4 Jose A. Torres 4/19/93 +-- Version 0.5 Jose A. Torres 4/20/93 Added RANDOM() +-- Version 0.6 Jose A. Torres 4/23/93 Renamed RANDOM as +-- UNIFORM. Modified +-- rights banner. +-- Version 0.7 Jose A. Torres 5/28/93 Rev up for compatibility +-- with package body. +------------------------------------------------------------- +Library IEEE; + +Package MATH_REAL is + + -- + -- commonly used constants + -- + constant MATH_E : real := 2.71828_18284_59045_23536; + -- value of e + constant MATH_1_E: real := 0.36787_94411_71442_32160; + -- value of 1/e + constant MATH_PI : real := 3.14159_26535_89793_23846; + -- value of pi + constant MATH_1_PI : real := 0.31830_98861_83790_67154; + -- value of 1/pi + constant MATH_LOG_OF_2: real := 0.69314_71805_59945_30942; + -- natural log of 2 + constant MATH_LOG_OF_10: real := 2.30258_50929_94045_68402; + -- natural log of10 + constant MATH_LOG2_OF_E: real := 1.44269_50408_88963_4074; + -- log base 2 of e + constant MATH_LOG10_OF_E: real := 0.43429_44819_03251_82765; + -- log base 10 of e + constant MATH_SQRT2: real := 1.41421_35623_73095_04880; + -- sqrt of 2 + constant MATH_SQRT1_2: real := 0.70710_67811_86547_52440; + -- sqrt of 1/2 + constant MATH_SQRT_PI: real := 1.77245_38509_05516_02730; + -- sqrt of pi + constant MATH_DEG_TO_RAD: real := 0.01745_32925_19943_29577; + -- conversion factor from degree to radian + constant MATH_RAD_TO_DEG: real := 57.29577_95130_82320_87685; + -- conversion factor from radian to degree + + -- + -- attribute for functions whose implementation is foreign (C native) + -- + attribute FOREIGN : string; -- predefined attribute in VHDL-1992 + + -- + -- function declarations + -- + function SIGN (X: real ) return real; + -- returns 1.0 if X > 0.0; 0.0 if X == 0.0; -1.0 if X < 0.0 + + function CEIL (X : real ) return real; + -- returns smallest integer value (as real) not less than X + + function FLOOR (X : real ) return real; + -- returns largest integer value (as real) not greater than X + + function ROUND (X : real ) return real; + -- returns integer FLOOR(X + 0.5) if X > 0; + -- return integer CEIL(X - 0.5) if X < 0 + + function FMAX (X, Y : real ) return real; + -- returns the algebraically larger of X and Y + + function FMIN (X, Y : real ) return real; + -- returns the algebraically smaller of X and Y + + procedure UNIFORM (variable Seed1,Seed2:inout integer; variable X:out real); + -- returns a pseudo-random number with uniform distribution in the + -- interval (0.0, 1.0). + -- Before the first call to UNIFORM, the seed values (Seed1, Seed2) must + -- be initialized to values in the range [1, 2147483562] and + -- [1, 2147483398] respectively. The seed values are modified after + -- each call to UNIFORM. + -- This random number generator is portable for 32-bit computers, and + -- it has period ~2.30584*(10**18) for each set of seed values. + -- + -- For VHDL-1992, the seeds will be global variables, functions to + -- initialize their values (INIT_SEED) will be provided, and the UNIFORM + -- procedure call will be modified accordingly. + + function SRAND (seed: in integer ) return integer; + -- + -- sets value of seed for sequence of + -- pseudo-random numbers. + -- It uses the foreign native C function srand(). + attribute FOREIGN of SRAND : function is "C_NATIVE"; + + function RAND return integer; + -- + -- returns an integer pseudo-random number with uniform distribution. + -- It uses the foreign native C function rand(). + -- Seed for the sequence is initialized with the + -- SRAND() function and value of the seed is changed every + -- time SRAND() is called, but it is not visible. + -- The range of generated values is platform dependent. + attribute FOREIGN of RAND : function is "C_NATIVE"; + + function GET_RAND_MAX return integer; + -- + -- returns the upper bound of the range of the + -- pseudo-random numbers generated by RAND(). + -- The support for this function is platform dependent, and + -- it uses foreign native C functions or constants. + -- It may not be available in some platforms. + -- Note: the value of (RAND() / GET_RAND_MAX()) is a + -- pseudo-random number distributed between 0 & 1. + attribute FOREIGN of GET_RAND_MAX : function is "C_NATIVE"; + + function SQRT (X : real ) return real; + -- returns square root of X; X >= 0 + + function CBRT (X : real ) return real; + -- returns cube root of X + + function "**" (X : integer; Y : real) return real; + -- returns Y power of X ==> X**Y; + -- error if X = 0 and Y <= 0.0 + -- error if X < 0 and Y does not have an integer value + + function "**" (X : real; Y : real) return real; + -- returns Y power of X ==> X**Y; + -- error if X = 0.0 and Y <= 0.0 + -- error if X < 0.0 and Y does not have an integer value + + function EXP (X : real ) return real; + -- returns e**X; where e = MATH_E + + function LOG (X : real ) return real; + -- returns natural logarithm of X; X > 0 + + function LOG (BASE: positive; X : real) return real; + -- returns logarithm base BASE of X; X > 0 + + function SIN (X : real ) return real; + -- returns sin X; X in radians + + function COS ( X : real ) return real; + -- returns cos X; X in radians + + function TAN (X : real ) return real; + -- returns tan X; X in radians + -- X /= ((2k+1) * PI/2), where k is an integer + + function ASIN (X : real ) return real; + -- returns -PI/2 < asin X < PI/2; | X | <= 1 + + function ACOS (X : real ) return real; + -- returns 0 < acos X < PI; | X | <= 1 + + function ATAN (X : real) return real; + -- returns -PI/2 < atan X < PI/2 + + function ATAN2 (X : real; Y : real) return real; + -- returns atan (X/Y); -PI < atan2(X,Y) < PI; Y /= 0.0 + + function SINH (X : real) return real; + -- hyperbolic sine; returns (e**X - e**(-X))/2 + + function COSH (X : real) return real; + -- hyperbolic cosine; returns (e**X + e**(-X))/2 + + function TANH (X : real) return real; + -- hyperbolic tangent; -- returns (e**X - e**(-X))/(e**X + e**(-X)) + + function ASINH (X : real) return real; + -- returns ln( X + sqrt( X**2 + 1)) + + function ACOSH (X : real) return real; + -- returns ln( X + sqrt( X**2 - 1)); X >= 1 + + function ATANH (X : real) return real; + -- returns (ln( (1 + X)/(1 - X)))/2 ; | X | < 1 + +end MATH_REAL; diff --git a/lib/Standard/ieee/new/numeric_bit.vhdl b/lib/Standard/ieee/new/numeric_bit.vhdl new file mode 100644 index 0000000..c8bd465 --- /dev/null +++ b/lib/Standard/ieee/new/numeric_bit.vhdl @@ -0,0 +1,813 @@ +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +--This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +--as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_BIT) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents an UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type BIT. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions, clock detection +-- : functions, and other utility functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_BIT. The NUMERIC_BIT package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- ----------------------------------------------------------------------------- +-- Version : 2.4 +-- Date : 12 April 1995 +-- ---------------------------------------------------------------------------- + +package NUMERIC_BIT is + constant CopyRightNotice: STRING + := "Copyright 1995 IEEE. All rights reserved."; + + --=========================================================================== + -- Numeric array type definitions + --=========================================================================== + + type UNSIGNED is array (NATURAL range <> ) of BIT; + type SIGNED is array (NATURAL range <> ) of BIT; + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector ARG. + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --=========================================================================== + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L(may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --=========================================================================== + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --=========================================================================== + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- size L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- size R'LENGTH before multiplication. + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of size L'LENGTH before + -- multiplication. + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of size R'LENGTH before + -- multiplication. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- Comparison Operators + --=========================================================================== + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --=========================================================================== + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + -- Shift and Rotate Functions + --=========================================================================== + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT rightmost bits are lost. + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits, except ARG'LEFT, are lost. + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost bit, ARG'LEFT. + -- The COUNT rightmost bits are lost. + + --=========================================================================== + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED vector COUNT times. + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED vector COUNT times. + + --=========================================================================== + + ----------------------------------------------------------------------------- + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)) + + ----------------------------------------------------------------------------- + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + --=========================================================================== + -- RESIZE Functions + --=========================================================================== + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the UNSIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + --=========================================================================== + -- Conversion Functions + --=========================================================================== + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified size. + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified size. + + --=========================================================================== + -- Logical Operators + --=========================================================================== + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ----------------------------------------------------------------------------- + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ----------------------------------------------------------------------------- + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + --=========================================================================== + -- Edge Detection Functions + --=========================================================================== + + -- Id: E.1 + function RISING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '0' to a '1'. + + -- Id: E.2 + function FALLING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '1' to a '0'. + +end NUMERIC_BIT; diff --git a/lib/Standard/ieee/new/numeric_std.vhdl b/lib/Standard/ieee/new/numeric_std.vhdl new file mode 100644 index 0000000..471a78c --- /dev/null +++ b/lib/Standard/ieee/new/numeric_std.vhdl @@ -0,0 +1,853 @@ +-- -------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +--This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +--as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_STD) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type STD_LOGIC. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_STD. The NUMERIC_STD package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- +-- -------------------------------------------------------------------- +-- modification history : +-- -------------------------------------------------------------------- +-- Version: 2.4 +-- Date : 12 April 1995 +-- ---------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.all; + +package NUMERIC_STD is + constant CopyRightNotice: STRING + := "Copyright 1995 IEEE. All rights reserved."; + + --=========================================================================== + -- Numeric array type definitions + --=========================================================================== + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector ARG. + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --=========================================================================== + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L(may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --=========================================================================== + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" (L: UNSIGNED;R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --=========================================================================== + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'LENGTH before multiplication. + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of SIZE L'LENGTH before + -- multiplication. + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of SIZE R'LENGTH before + -- multiplication. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- Comparison Operators + --=========================================================================== + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --=========================================================================== + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + -- Shift and Rotate Functions + --=========================================================================== + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT rightmost elements are lost. + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost + -- element, ARG'LEFT. The COUNT rightmost elements are lost. + + --=========================================================================== + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED + -- vector COUNT times. + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED + -- vector COUNT times. + + --=========================================================================== + + --=========================================================================== + + ----------------------------------------------------------------------------- + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)) + + ----------------------------------------------------------------------------- + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + --=========================================================================== + -- RESIZE Functions + --=========================================================================== + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + --=========================================================================== + -- Conversion Functions + --=========================================================================== + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified SIZE. + + --=========================================================================== + -- Logical Operators + --=========================================================================== + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + -- -------------------------------------------------------------------------- + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + -- -------------------------------------------------------------------------- + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + -- --------------------------------------------------------------------------- + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + -- --------------------------------------------------------------------------- + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + --=========================================================================== + -- Match Functions + --=========================================================================== + + -- Id: M.1 + function STD_MATCH (L, R: STD_ULOGIC) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.2 + function STD_MATCH (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.3 + function STD_MATCH (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.4 + function STD_MATCH (L, R: STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.5 + function STD_MATCH (L, R: STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + --=========================================================================== + -- Translation Functions + --=========================================================================== + + -- Id: T.1 + function TO_01 (S: UNSIGNED; XMAP: STD_LOGIC := '0') return UNSIGNED; + -- Result subtype: UNSIGNED(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. + + -- Id: T.2 + function TO_01 (S: SIGNED; XMAP: STD_LOGIC := '0') return SIGNED; + -- Result subtype: SIGNED(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. + +end NUMERIC_STD; diff --git a/lib/Standard/ieee/new/standard.vhdl b/lib/Standard/ieee/new/standard.vhdl new file mode 100644 index 0000000..79b1fd3 --- /dev/null +++ b/lib/Standard/ieee/new/standard.vhdl @@ -0,0 +1,133 @@ +-- The sven STANDARD package. +-- This design unit contains some special tokens, which are only +-- recognized by the analyzer when it is in special "bootstrap" mode. + +package STANDARD is + + -- predefined enumeration types: + + type BOOLEAN is (FALSE, TRUE); + + type BIT is ('0', '1'); + + type CHARACTER is ( + NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, + BS, HT, LF, VT, FF, CR, SO, SI, + DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, + CAN, EM, SUB, ESC, FSP, GSP, RSP, USP, + + ' ', '!', '"', '#', '$', '%', '&', ''', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\', ']', '^', '_', + + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', DEL, + C128, C129, C130, C131, C132, C133, C134, C135, + C136, C137, C138, C139, C140, C141, C142, C143, + C144, C145, C146, C147, C148, C149, C150, C151, + C152, C153, C154, C155, C156, C157, C158, C159, + ' ', '¡', '¢', '£', '¤', '¥', '¦', '§', + '¨', '©', 'ª', '«', '¬', '­', '®', '¯', + '°', '±', '²', '³', '´', 'µ', '¶', '·', + '¸', '¹', 'º', '»', '¼', '½', '¾', '¿', + 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Æ', 'Ç', + 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', + 'Ð', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', '×', + 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý', 'Þ', 'ß', + 'à', 'á', 'â', 'ã', 'ä', 'å', 'æ', 'ç', + 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', + 'ð', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', '÷', + 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'þ', 'ÿ'); + + + + type SEVERITY_LEVEL is (NOTE, WARNING, ERROR, FAILURE); + + -- predefined numeric types: + + -- Do INTEGER first to aid implicit declarations of "**". + type INTEGER is range -2147483647 to 2147483647; + + type $UNIVERSAL_INTEGER is range $- to $+; + + type $UNIVERSAL_REAL is range $-. to $+.; + + function "*" ($LEFT: $UNIVERSAL_REAL; $RIGHT: $UNIVERSAL_INTEGER) + return $UNIVERSAL_REAL; + + function "*" ($LEFT: $UNIVERSAL_INTEGER; $RIGHT: $UNIVERSAL_REAL) + return $UNIVERSAL_REAL; + + function "/" ($LEFT: $UNIVERSAL_REAL; $RIGHT: $UNIVERSAL_INTEGER) + return $UNIVERSAL_REAL; + + type REAL is range $-. to $+.; + + -- predefined type TIME: + + type TIME is range $- to $+ + units + fs; -- femtosecond + ps = 1000 fs; -- picosecond + ns = 1000 ps; -- nanosecond + us = 1000 ns; -- microsecond + ms = 1000 us; -- millisecond + sec = 1000 ms; -- second + min = 60 sec; -- minute + hr = 60 min; -- hour; + end units; + + -- subtype used internally for checking time expressions for non-negativness: + + subtype $NATURAL_TIME is TIME range 0 sec to TIME'HIGH; + + subtype DELAY_LENGTH is TIME range 0 fs to TIME'HIGH; + + -- function that returns the current simulation time: + + impure function NOW return TIME; + + -- predefined numeric subtypes: + + subtype NATURAL is INTEGER range 0 to INTEGER'HIGH; + + subtype POSITIVE is INTEGER range 1 to INTEGER'HIGH; + + -- predefined array types: + + type STRING is array (POSITIVE range <>) of CHARACTER; + + type BIT_VECTOR is array (NATURAL range <>) of BIT; + +--type FILE_OPEN_KIND is (READ_OPEN, WRITE_OPEN, APPEND_OPEN); + + type FILE_OPEN_KIND is (READ_MODE, WRITE_MODE, APPEND_MODE); + + type FILE_OPEN_STATUS is (OPEN_OK, STATUS_ERROR, NAME_ERROR, MODE_ERROR); + + attribute FOREIGN: STRING; + + -- + -- The rest of this package is SVEN specific stuff required to make + -- this implementation go. + -- Note that all things are declared use leading $ characters, so we don't + -- trample the user's name space. + -- + + attribute $BUILTIN: BOOLEAN; + + procedure $RTINDEX (I: NATURAL; FIRSTARG: INTEGER; PASSAP,SAVEFREGS: BOOLEAN); + procedure $RTSYMBOL (S: STRING; FIRSTARG: INTEGER; PASSAP,SAVEFREGS: BOOLEAN); + + attribute $BUILTIN of all: function is TRUE; + attribute $BUILTIN of all: procedure is TRUE; + +end STANDARD; diff --git a/lib/Standard/ieee/new/std_logic_1164.vhdl b/lib/Standard/ieee/new/std_logic_1164.vhdl new file mode 100644 index 0000000..5b165d2 --- /dev/null +++ b/lib/Standard/ieee/new/std_logic_1164.vhdl @@ -0,0 +1,178 @@ +-- -------------------------------------------------------------------- +-- +-- Title : std_logic_1164 multi-value logic system +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- Developers: IEEE model standards group (par 1164) +-- Purpose : This packages defines a standard for designers +-- : to use in describing the interconnection data types +-- : used in vhdl modeling. +-- : +-- Limitation: The logic system defined in this package may +-- : be insufficient for modeling switched transistors, +-- : since such a requirement is out of the scope of this +-- : effort. Furthermore, mathematics, primitives, +-- : timing standards, etc. are considered orthogonal +-- : issues as it relates to this package and are therefore +-- : beyond the scope of this effort. +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : std_logic_1164. The std_logic_1164 package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- -------------------------------------------------------------------- +-- modification history : +-- -------------------------------------------------------------------- +-- version | mod. date:| +-- v4.200 | 01/02/92 | +-- -------------------------------------------------------------------- + +PACKAGE std_logic_1164 IS + + ------------------------------------------------------------------- + -- logic state system (unresolved) + ------------------------------------------------------------------- + TYPE std_ulogic IS ( 'U', -- Uninitialized + 'X', -- Forcing Unknown + '0', -- Forcing 0 + '1', -- Forcing 1 + 'Z', -- High Impedance + 'W', -- Weak Unknown + 'L', -- Weak 0 + 'H', -- Weak 1 + '-' -- Don't care + ); + ------------------------------------------------------------------- + -- unconstrained array of std_ulogic for use with the resolution function + ------------------------------------------------------------------- + TYPE std_ulogic_vector IS ARRAY ( NATURAL RANGE <> ) OF std_ulogic; + + ------------------------------------------------------------------- + -- resolution function + ------------------------------------------------------------------- + FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic; + + ------------------------------------------------------------------- + -- *** industry standard logic type *** + ------------------------------------------------------------------- + SUBTYPE std_logic IS resolved std_ulogic; + + ------------------------------------------------------------------- + -- unconstrained array of std_logic for use in declaring signal arrays + ------------------------------------------------------------------- + TYPE std_logic_vector IS ARRAY ( NATURAL RANGE <>) OF std_logic; + + ------------------------------------------------------------------- + -- common subtypes + ------------------------------------------------------------------- + SUBTYPE X01 IS resolved std_ulogic RANGE 'X' TO '1'; -- ('X','0','1') + SUBTYPE X01Z IS resolved std_ulogic RANGE 'X' TO 'Z'; -- ('X','0','1','Z') + SUBTYPE UX01 IS resolved std_ulogic RANGE 'U' TO '1'; -- ('U','X','0','1') + SUBTYPE UX01Z IS resolved std_ulogic RANGE 'U' TO 'Z'; -- ('U','X','0','1','Z') + + ------------------------------------------------------------------- + -- overloaded logical operators + ------------------------------------------------------------------- + + FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + function "xnor" ( l : std_ulogic; r : std_ulogic ) return ux01; + FUNCTION "not" ( l : std_ulogic ) RETURN UX01; + + ------------------------------------------------------------------- + -- vectorized overloaded logical operators + ------------------------------------------------------------------- + FUNCTION "and" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "and" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "nand" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nand" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "or" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "or" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "nor" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "xor" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "xor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this std_logic_1164 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + function "xnor" ( l, r : std_logic_vector ) return std_logic_vector; + function "xnor" ( l, r : std_ulogic_vector ) return std_ulogic_vector; + + FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector; + + ------------------------------------------------------------------- + -- conversion functions + ------------------------------------------------------------------- + FUNCTION To_bit ( s : std_ulogic; xmap : BIT := '0') + RETURN BIT; + FUNCTION To_bitvector ( s : std_logic_vector ; xmap : BIT := '0') + RETURN BIT_VECTOR; + FUNCTION To_bitvector ( s : std_ulogic_vector; xmap : BIT := '0') + RETURN BIT_VECTOR; + + FUNCTION To_StdULogic (b : BIT ) RETURN std_ulogic; + FUNCTION To_StdLogicVector (b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_StdLogicVector (s : std_ulogic_vector) RETURN std_logic_vector; + FUNCTION To_StdULogicVector(b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_StdULogicVector(s : std_logic_vector) RETURN std_ulogic_vector; + + ------------------------------------------------------------------- + -- strength strippers and type convertors + ------------------------------------------------------------------- + + FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_X01 ( s : std_ulogic ) RETURN X01; + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_X01 ( b : BIT ) RETURN X01; + + FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z; + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_X01Z ( b : BIT ) RETURN X01Z; + + FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01; + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_UX01 ( b : BIT ) RETURN UX01; + + ------------------------------------------------------------------- + -- edge detection + ------------------------------------------------------------------- + FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN; + FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN; + + ------------------------------------------------------------------- + -- object contains an unknown + ------------------------------------------------------------------- + FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN; + FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN; + FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN; + +END std_logic_1164; diff --git a/lib/Standard/ieee/new/std_logic_arith_ex.vhdl b/lib/Standard/ieee/new/std_logic_arith_ex.vhdl new file mode 100644 index 0000000..6a6dc2c --- /dev/null +++ b/lib/Standard/ieee/new/std_logic_arith_ex.vhdl @@ -0,0 +1,217 @@ +-- -------------------------------------------------------------------- +-- +-- Title : STD_LOGIC_ARITH arithmetic support for STD_ULOGIC/ +-- : STD_LOGIC_VECTOR data type +-- Library : This package shall be compiled into a logical library +-- : named IEEE. +-- Purpose : To support unsigned arithmetic operations such as +-- : addition, subtraction, multiplication etc. for std_ulogic +-- : and std_logic_vector data types. Besides it supports +-- : functions and operators for Conditional operations, +-- : shift operations, relational operation between integer +-- : and std_logic_vector types, aligning size between operands +-- : of different sizes, type conversion. +-- : It also supports a set of arithemtic, conversion, and +-- : comparison functions for SIGNED, UNSIGNED, SMALL_INT, +-- : INTEGER, STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. +-- : +-- : Modification History: TH, 24th Jan., 1994 +-- : Following functions are overloaded for STD_ULOGIC_VECTOR +-- : type: "+", "-", "*", "cond_op", "<", ">", "<=", ">=", "=", +-- : "/=", sh_left, sh_right, align_size and "to_integer" +-- : New functions added are: +-- : To_StdUlogicVector (oper: INTEGER; length: NATURAL) +-- : return STD_ULOGIC_VECTOR +-- : "+"(op1: STD_ULOGIC; op2: STD_ULOGIC) return STD_ULOGIC; +-- : "-"(op1: STD_ULOGIC; op2: STD_ULOGIC) return STD_ULOGIC; +-- +-- : Name changes from STD_LOGIC_ARITH to STD_LOGIC_ARITH +-- : operator "/" added. +-- : Vinaya: 13/9/94. +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + + +package STD_LOGIC_ARITH is + +-- ADD/SUBTRACT OPERATORS + + function "+"(op1, op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(op1: STD_LOGIC_VECTOR; op2: STD_ULOGIC) + return STD_LOGIC_VECTOR; + function "+"(op1: STD_ULOGIC; op2: STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function "+"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return STD_LOGIC_VECTOR; + + function "+"(op1, op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC_VECTOR; op2: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC; op2: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function "+"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) + return STD_ULOGIC_VECTOR; + function "+"(op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + + function "-"(op1, op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(op1: STD_LOGIC_VECTOR; op2: STD_ULOGIC) + return STD_LOGIC_VECTOR; + function "-"(op1: STD_ULOGIC; op2: STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function "-"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return STD_LOGIC_VECTOR; + + function "-"(op1, op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC_VECTOR; op2: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC; op2: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function "-"(op1: INTEGER; op2: STD_ULOGIC_VECTOR)return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC_VECTOR; op2: INTEGER)return STD_ULOGIC_VECTOR; + function "-"(op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + -- UNARY OPERATORS + + function "+" (op1: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+" (op1: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + +-- MULTIPLYING OPERATORS + + function "*" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "*" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function "*" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) + return STD_LOGIC_VECTOR; + function "*" (op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + function "*" (op1, op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "*" (op1: STD_ULOGIC; op2 : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function "*" (op1: STD_ULOGIC_VECTOR; op2 : STD_ULOGIC) + return STD_ULOGIC_VECTOR; + +-- DIVISION OPERATORS +-- The division operators are only for internal use +-- It is not advisible to use them in design. + + function "/" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "/" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) + return STD_LOGIC_VECTOR; + function "/" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) + return STD_ULOGIC; + function "/" (op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + +-- CONDITIONAL FUNCTIONS + + function cond_op (cond : boolean; left_val, right_val: STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function cond_op (cond : boolean; left_val, right_val: STD_ULOGIC) + return STD_ULOGIC; + function cond_op (cond : boolean; left_val, right_val: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + +-- RELATIONAL OPERATORS + + function "<"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "<="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "/="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + + function "<"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "<"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "<="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "<="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function ">"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function ">="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "/="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "/="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + +-- SHIFT OPERATORS + + function sh_left(op1: STD_LOGIC_VECTOR; op2: NATURAL) + return STD_LOGIC_VECTOR; + function sh_right(op1: STD_LOGIC_VECTOR; op2: NATURAL) + return STD_LOGIC_VECTOR; + function sh_left(op1: STD_ULOGIC_VECTOR; op2: NATURAL) + return STD_ULOGIC_VECTOR; + function sh_right(op1: STD_ULOGIC_VECTOR; op2: NATURAL) + return STD_ULOGIC_VECTOR; + + +-- FUNCTIONS TO ALLOW ASSIGNMENTS OF STD_LOGIC_VECTOR OF UNEQUAL SIZES + + + function align_size (oper : STD_LOGIC_VECTOR; size : NATURAL) + return STD_LOGIC_VECTOR; + function align_size (oper : STD_ULOGIC; size : NATURAL) + return STD_LOGIC_VECTOR; + function align_size (oper : STD_ULOGIC_VECTOR; size : NATURAL) + return STD_ULOGIC_VECTOR; + function align_size (oper : STD_ULOGIC; size : NATURAL) + return STD_ULOGIC_VECTOR; + +-- CONVERSION TO INTEGER FROM STD_LOGIC AND STD_LOGIC_VECTOR + + function to_integer (oper : STD_LOGIC_VECTOR) return INTEGER; + function to_integer (oper: STD_ULOGIC) return INTEGER; + function to_integer (oper : STD_ULOGIC_VECTOR) return INTEGER; + + +-- CONVERSION TO STD_LOGIC_VECTOR FROM INTEGER + + function To_StdLogicVector (oper: INTEGER; length: NATURAL) + return STD_LOGIC_VECTOR; + function To_StdUlogicVector (oper: INTEGER; length: NATURAL) + return STD_ULOGIC_VECTOR; + +-- UTILITY FUNCTIONS + + function drive (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function drive (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function Sense (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) return STD_ULOGIC; + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + +-- CONVERSION TABLE FOR TO_INTEGER + + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + +end STD_LOGIC_ARITH; + diff --git a/lib/Standard/ieee/new/std_logic_arith_syn.vhdl b/lib/Standard/ieee/new/std_logic_arith_syn.vhdl new file mode 100644 index 0000000..e259bc3 --- /dev/null +++ b/lib/Standard/ieee/new/std_logic_arith_syn.vhdl @@ -0,0 +1,192 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + diff --git a/lib/Standard/ieee/new/std_logic_signed.vhdl b/lib/Standard/ieee/new/std_logic_signed.vhdl new file mode 100644 index 0000000..938ebbc --- /dev/null +++ b/lib/Standard/ieee/new/std_logic_signed.vhdl @@ -0,0 +1,83 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_SIGNED -- +-- -- +-- -- +-- Date: 09/11/91 KN -- +-- 10/08/92 AMT change std_ulogic to signed std_logic -- +-- 10/28/92 AMT added signed functions, -, ABS -- +-- -- +-- Purpose: -- +-- A set of signed arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: Comparision of same length std_logic_vector is defined -- +-- in the LRM. The interpretation is for unsigned vectors -- +-- This package will "overload" that definition. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_SIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "ABS"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_SIGNED; diff --git a/lib/Standard/ieee/new/std_logic_textio.vhdl b/lib/Standard/ieee/new/std_logic_textio.vhdl new file mode 100644 index 0000000..ac39248 --- /dev/null +++ b/lib/Standard/ieee/new/std_logic_textio.vhdl @@ -0,0 +1,73 @@ +-- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. +-- +-- This source file may be used and distributed without restriction +-- provided that this copyright statement is not removed from the file +-- and that any derivative work contains this copyright notice. +-- +-- Package name: STD_LOGIC_TEXTIO +-- +-- Purpose: This package overloads the standard TEXTIO procedures +-- READ and WRITE. +-- +-- Author: CRC, TS +-- +---------------------------------------------------------------------------- + +use STD.textio.all; +library IEEE; +use IEEE.std_logic_1164.all; + +package STD_LOGIC_TEXTIO is +--synopsys synthesis_off + -- Read and Write procedures for STD_ULOGIC and STD_ULOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD: out BOOLEAN); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out +BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Read and Write procedures for STD_LOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out +BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- + -- Read and Write procedures for Hex and Octal values. + -- The values appear in the file as a series of characters + -- between 0-F (Hex), or 0-7 (Octal) respectively. + -- + + -- Hex + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: +out BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out +BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Octal + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: +out BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out +BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + +--synopsys synthesis_on +end STD_LOGIC_TEXTIO; diff --git a/lib/Standard/ieee/new/std_logic_unsigned.vhdl b/lib/Standard/ieee/new/std_logic_unsigned.vhdl new file mode 100644 index 0000000..8cd5377 --- /dev/null +++ b/lib/Standard/ieee/new/std_logic_unsigned.vhdl @@ -0,0 +1,79 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_UNSIGNED -- +-- -- +-- -- +-- Date: 09/11/92 KN -- +-- 10/08/92 AMT -- +-- -- +-- Purpose: -- +-- A set of unsigned arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: comparision of same length discrete arrays is defined -- +-- by the LRM. This package will "overload" those -- +-- definitions -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_UNSIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_UNSIGNED; diff --git a/lib/Standard/ieee/new/textio.vhd b/lib/Standard/ieee/new/textio.vhd new file mode 100644 index 0000000..9795637 --- /dev/null +++ b/lib/Standard/ieee/new/textio.vhd @@ -0,0 +1,86 @@ +-- textio.vhdl + +library std; use std.standard.all; -- needed for bootstrap mode + +package TEXTIO is + + -- Type Definitions for Text I/O + + type LINE is access STRING; -- a line is a pointer to a STRING value + + type TEXT is file of STRING; -- a file of variable-length ASCII records + + type SIDE is (RIGHT, LEFT); -- for justifying output data within fields + + subtype WIDTH is NATURAL; -- for specifying widths of output fields + + -- Standard Text Files + + file INPUT: TEXT open READ_MODE is "STD_INPUT"; + + file OUTPUT: TEXT open WRITE_MODE is "STD_OUTPUT"; + + -- Input Routines for Standard Types + + procedure READLINE (file F: TEXT; L: inout LINE); + + procedure READ (L: inout LINE; VALUE: out BIT; GOOD: out BOOLEAN); + procedure READ (L: inout LINE; VALUE: out BIT); + + procedure READ (L: inout LINE; VALUE: out BIT_VECTOR; GOOD: out BOOLEAN); + procedure READ (L: inout LINE; VALUE: out BIT_VECTOR); + + procedure READ (L: inout LINE; VALUE: out BOOLEAN; GOOD: out BOOLEAN); + procedure READ (L: inout LINE; VALUE: out BOOLEAN); + + procedure READ (L: inout LINE; VALUE: out CHARACTER; GOOD: out BOOLEAN); + procedure READ (L: inout LINE; VALUE: out CHARACTER); + + procedure READ (L: inout LINE; VALUE: out INTEGER; GOOD: out BOOLEAN); + procedure READ (L: inout LINE; VALUE: out INTEGER); + + procedure READ (L: inout LINE; VALUE: out REAL; GOOD: out BOOLEAN); + procedure READ (L: inout LINE; VALUE: out REAL); + + procedure READ (L: inout LINE; VALUE: out STRING; GOOD: out BOOLEAN); + procedure READ (L: inout LINE; VALUE: out STRING); + + procedure READ (L: inout LINE; VALUE: out TIME; GOOD: out BOOLEAN); + procedure READ (L: inout LINE; VALUE: out TIME); + + -- Output Routines for Standard Types + + procedure WRITELINE (file F: TEXT; L: inout LINE); + + procedure WRITE (L: inout LINE; VALUE: in BIT; + JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0); + + procedure WRITE (L: inout LINE; VALUE: in BIT_VECTOR; + JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0); + + procedure WRITE (L: inout LINE; VALUE: in BOOLEAN; + JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0); + + procedure WRITE (L: inout LINE; VALUE: in CHARACTER; + JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0); + + procedure WRITE (L: inout LINE; VALUE: in INTEGER; + JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0); + + procedure WRITE (L: inout LINE; VALUE: in REAL; + JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0; + DIGITS: in NATURAL := 0); + + procedure WRITE (L: inout LINE; VALUE: in STRING; + JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0); + + procedure WRITE (L: inout LINE; VALUE: in TIME; + JUSTIFIED: in SIDE := RIGHT; FIELD: in WIDTH := 0; + UNIT: in TIME := ns); + + -- File Position Predicates + + function ENDLINE (L: in LINE) return BOOLEAN; + + +end TEXTIO; diff --git a/lib/Standard/ieee/numeric_bit.vhdl b/lib/Standard/ieee/numeric_bit.vhdl new file mode 100644 index 0000000..c8bd465 --- /dev/null +++ b/lib/Standard/ieee/numeric_bit.vhdl @@ -0,0 +1,813 @@ +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +--This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +--as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_BIT) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents an UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type BIT. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions, clock detection +-- : functions, and other utility functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_BIT. The NUMERIC_BIT package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- ----------------------------------------------------------------------------- +-- Version : 2.4 +-- Date : 12 April 1995 +-- ---------------------------------------------------------------------------- + +package NUMERIC_BIT is + constant CopyRightNotice: STRING + := "Copyright 1995 IEEE. All rights reserved."; + + --=========================================================================== + -- Numeric array type definitions + --=========================================================================== + + type UNSIGNED is array (NATURAL range <> ) of BIT; + type SIGNED is array (NATURAL range <> ) of BIT; + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector ARG. + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --=========================================================================== + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L(may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --=========================================================================== + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --=========================================================================== + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- size L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- size R'LENGTH before multiplication. + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of size L'LENGTH before + -- multiplication. + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of size R'LENGTH before + -- multiplication. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- Comparison Operators + --=========================================================================== + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --=========================================================================== + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + -- Shift and Rotate Functions + --=========================================================================== + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT rightmost bits are lost. + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits, except ARG'LEFT, are lost. + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost bit, ARG'LEFT. + -- The COUNT rightmost bits are lost. + + --=========================================================================== + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED vector COUNT times. + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED vector COUNT times. + + --=========================================================================== + + ----------------------------------------------------------------------------- + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)) + + ----------------------------------------------------------------------------- + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + --=========================================================================== + -- RESIZE Functions + --=========================================================================== + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the UNSIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + --=========================================================================== + -- Conversion Functions + --=========================================================================== + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified size. + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified size. + + --=========================================================================== + -- Logical Operators + --=========================================================================== + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ----------------------------------------------------------------------------- + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ----------------------------------------------------------------------------- + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + --=========================================================================== + -- Edge Detection Functions + --=========================================================================== + + -- Id: E.1 + function RISING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '0' to a '1'. + + -- Id: E.2 + function FALLING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '1' to a '0'. + +end NUMERIC_BIT; diff --git a/lib/Standard/ieee/numeric_bit_body.vhd b/lib/Standard/ieee/numeric_bit_body.vhd new file mode 100644 index 0000000..2825cf9 --- /dev/null +++ b/lib/Standard/ieee/numeric_bit_body.vhd @@ -0,0 +1,2573 @@ +-- ----------------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +-- This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +-- as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_BIT) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents an UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type BIT. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions, clock detection +-- : functions, and other utility functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_BIT. The NUMERIC_BIT package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- ----------------------------------------------------------------------------- +-- Version : 2.4 +-- Date : 12 April 1995 +-- ----------------------------------------------------------------------------- + +package NUMERIC_BIT is + constant CopyRightNotice: STRING + := "Copyright 1995 IEEE. All rights reserved."; + + --============================================================================ + -- Numeric array type definitions + --============================================================================ + + type UNSIGNED is array (NATURAL range <> ) of BIT; + type SIGNED is array (NATURAL range <> ) of BIT; + + --============================================================================ + -- Arithmetic Operators: + --============================================================================ + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector ARG. + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --============================================================================ + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L(may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- size L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- size R'LENGTH before multiplication. + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of size L'LENGTH before + -- multiplication. + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of size R'LENGTH before + -- multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT rightmost bits are lost. + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits, except ARG'LEFT, are lost. + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost bit, ARG'LEFT. + -- The COUNT rightmost bits are lost. + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED vector COUNT times. + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED vector COUNT times. + + --============================================================================ + + ------------------------------------------------------------------------------ + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)) + + ------------------------------------------------------------------------------ + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the UNSIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified size. + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified size. + + --============================================================================ + -- Logical Operators + --============================================================================ + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ------------------------------------------------------------------------------ + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ------------------------------------------------------------------------------ + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + --============================================================================ + -- Edge Detection Functions + --============================================================================ + + -- Id: E.1 + function RISING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '0' to a '1'. + + -- Id: E.2 + function FALLING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '1' to a '0'. + +end NUMERIC_BIT; + +--============================================================================== +--======================= Package Body ========================================= +--============================================================================== + +package body NUMERIC_BIT is + + -- null range array constants + + constant NAU: UNSIGNED(0 downto 1) := (others => '0'); + constant NAS: SIGNED(0 downto 1) := (others => '0'); + + -- implementation controls + + constant NO_WARNING: BOOLEAN := FALSE; -- default to emit warnings + + --=========================Local Subprograms ================================= + + function MAX (LEFT, RIGHT: INTEGER) return INTEGER is + begin + if LEFT > RIGHT then return LEFT; + else return RIGHT; + end if; + end MAX; + + function MIN (LEFT, RIGHT: INTEGER) return INTEGER is + begin + if LEFT < RIGHT then return LEFT; + else return RIGHT; + end if; + end MIN; + + function SIGNED_NUM_BITS (ARG: INTEGER) return NATURAL is + variable NBITS: NATURAL; + variable N: NATURAL; + begin + if ARG >= 0 then + N := ARG; + else + N := -(ARG+1); + end if; + NBITS := 1; + while N > 0 loop + NBITS := NBITS+1; + N := N / 2; + end loop; + return NBITS; + end SIGNED_NUM_BITS; + + function UNSIGNED_NUM_BITS (ARG: NATURAL) return NATURAL is + variable NBITS: NATURAL; + variable N: NATURAL; + begin + N := ARG; + NBITS := 1; + while N > 1 loop + NBITS := NBITS+1; + N := N / 2; + end loop; + return NBITS; + end UNSIGNED_NUM_BITS; + + ------------------------------------------------------------------------------ + -- this internal function computes the addition of two UNSIGNED + -- with input carry + -- * the two arguments are of the same length + + function ADD_UNSIGNED (L, R: UNSIGNED; C: BIT) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(L_LEFT downto 0) is R; + variable RESULT: UNSIGNED(L_LEFT downto 0); + variable CBIT: BIT := C; + begin + for I in 0 to L_LEFT loop + RESULT(I) := CBIT xor XL(I) xor XR(I); + CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); + end loop; + return RESULT; + end ADD_UNSIGNED; + + -- this internal function computes the addition of two SIGNED + -- with input carry + -- * the two arguments are of the same length + + function ADD_SIGNED (L, R: SIGNED; C: BIT) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(L_LEFT downto 0) is R; + variable RESULT: SIGNED(L_LEFT downto 0); + variable CBIT: BIT := C; + begin + for I in 0 to L_LEFT loop + RESULT(I) := CBIT xor XL(I) xor XR(I); + CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); + end loop; + return RESULT; + end ADD_SIGNED; + + ------------------------------------------------------------------------------ + + -- this internal procedure computes UNSIGNED division + -- giving the quotient and remainder. + procedure DIVMOD (NUM, XDENOM: UNSIGNED; XQUOT, XREMAIN: out UNSIGNED) is + variable TEMP: UNSIGNED(NUM'LENGTH downto 0); + variable QUOT: UNSIGNED(MAX(NUM'LENGTH, XDENOM'LENGTH)-1 downto 0); + alias DENOM: UNSIGNED(XDENOM'LENGTH-1 downto 0) is XDENOM; + variable TOPBIT: INTEGER; + begin + TEMP := "0"&NUM; + QUOT := (others => '0'); + TOPBIT := -1; + for J in DENOM'RANGE loop + if DENOM(J)='1' then + TOPBIT := J; + exit; + end if; + end loop; + assert TOPBIT >= 0 report "DIV, MOD, or REM by zero" severity ERROR; + + for J in NUM'LENGTH-(TOPBIT+1) downto 0 loop + if TEMP(TOPBIT+J+1 downto J) >= "0"&DENOM(TOPBIT downto 0) then + TEMP(TOPBIT+J+1 downto J) := (TEMP(TOPBIT+J+1 downto J)) + -("0"&DENOM(TOPBIT downto 0)); + QUOT(J) := '1'; + end if; + assert TEMP(TOPBIT+J+1)='0' + report "internal error in the division algorithm" + severity ERROR; + end loop; + XQUOT := RESIZE(QUOT, XQUOT'LENGTH); + XREMAIN := RESIZE(TEMP, XREMAIN'LENGTH); + end DIVMOD; + + -----------------Local Subprograms - shift/rotate ops------------------------- + + function XSLL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := (others => '0'); + begin + if COUNT <= ARG_L then + RESULT(ARG_L downto COUNT) := XARG(ARG_L-COUNT downto 0); + end if; + return RESULT; + end XSLL; + + function XSRL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := (others => '0'); + begin + if COUNT <= ARG_L then + RESULT(ARG_L-COUNT downto 0) := XARG(ARG_L downto COUNT); + end if; + return RESULT; + end XSRL; + + function XSRA (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0); + variable XCOUNT: NATURAL := COUNT; + begin + if ((ARG'LENGTH <= 1) or (XCOUNT = 0)) then return ARG; + else + if (XCOUNT > ARG_L) then XCOUNT := ARG_L; + end if; + RESULT(ARG_L-XCOUNT downto 0) := XARG(ARG_L downto XCOUNT); + RESULT(ARG_L downto (ARG_L - XCOUNT + 1)) := (others => XARG(ARG_L)); + end if; + return RESULT; + end XSRA; + + function XROL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := XARG; + variable COUNTM: INTEGER; + begin + COUNTM := COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L downto COUNTM) := XARG(ARG_L-COUNTM downto 0); + RESULT(COUNTM-1 downto 0) := XARG(ARG_L downto ARG_L-COUNTM+1); + end if; + return RESULT; + end XROL; + + function XROR (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := XARG; + variable COUNTM: INTEGER; + begin + COUNTM := COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L-COUNTM downto 0) := XARG(ARG_L downto COUNTM); + RESULT(ARG_L downto ARG_L-COUNTM+1) := XARG(COUNTM-1 downto 0); + end if; + return RESULT; + end XROR; + + ---------------- Local Subprograms - Relational Operators -------------------- + + -- General "=" for UNSIGNED vectors, same length + -- + function UNSIGNED_EQUAL (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) = BIT_VECTOR(R); + end UNSIGNED_EQUAL; + + -- + -- General "=" for SIGNED vectors, same length + -- + function SIGNED_EQUAL (L, R: SIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) = BIT_VECTOR(R); + end SIGNED_EQUAL; + + -- + -- General "<" for UNSIGNED vectors, same length + -- + function UNSIGNED_LESS (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) < BIT_VECTOR(R); + end UNSIGNED_LESS; + + -- + -- General "<" function for SIGNED vectors, same length + -- + function SIGNED_LESS (L, R: SIGNED) return BOOLEAN is + -- Need aliases to assure index direction + variable INTERN_L: SIGNED(0 to L'LENGTH-1); + variable INTERN_R: SIGNED(0 to R'LENGTH-1); + begin + INTERN_L := L; + INTERN_R := R; + INTERN_L(0) := not INTERN_L(0); + INTERN_R(0) := not INTERN_R(0); + return BIT_VECTOR(INTERN_L) < BIT_VECTOR(INTERN_R); + end SIGNED_LESS; + + -- + -- General "<=" function for UNSIGNED vectors, same length + -- + function UNSIGNED_LESS_OR_EQUAL (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) <= BIT_VECTOR(R); + end UNSIGNED_LESS_OR_EQUAL; + + -- + -- General "<=" function for SIGNED vectors, same length + -- + function SIGNED_LESS_OR_EQUAL (L, R: SIGNED) return BOOLEAN is + -- Need aliases to assure index direction + variable INTERN_L: SIGNED(0 to L'LENGTH-1); + variable INTERN_R: SIGNED(0 to R'LENGTH-1); + begin + INTERN_L := L; + INTERN_R := R; + INTERN_L(0) := not INTERN_L(0); + INTERN_R(0) := not INTERN_R(0); + return BIT_VECTOR(INTERN_L) <= BIT_VECTOR(INTERN_R); + end SIGNED_LESS_OR_EQUAL; + + --====================== Exported Functions ================================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + variable RESULT: SIGNED(ARG_LEFT downto 0); + begin + if ARG'LENGTH < 1 then return NAS; + end if; + RESULT := ARG; + if RESULT(RESULT'LEFT) = '1' then + RESULT := -RESULT; + end if; + return RESULT; + end "abs"; + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: SIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: SIGNED(ARG_LEFT downto 0); + variable CBIT: BIT := '1'; + begin + if ARG'LENGTH < 1 then return NAS; + end if; + for I in 0 to RESULT'LEFT loop + RESULT(I) := not(XARG(I)) xor CBIT; + CBIT := CBIT and not(XARG(I)); + end loop; + return RESULT; + end "-"; + + --============================================================================ + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + return ADD_UNSIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); + end "+"; + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + return ADD_SIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); + end "+"; + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L + TO_UNSIGNED(R, L'LENGTH); + end "+"; + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) + R; + end "+"; + + -- Id: A.7 + function "+" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L + TO_SIGNED(R, L'LENGTH); + end "+"; + + -- Id: A.8 + function "+" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) + R; + end "+"; + + --============================================================================ + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + return ADD_UNSIGNED(RESIZE(L, SIZE), + not(RESIZE(R, SIZE)), + '1'); + end "-"; + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + return ADD_SIGNED(RESIZE(L, SIZE), + not(RESIZE(R, SIZE)), + '1'); + end "-"; + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L - TO_UNSIGNED(R, L'LENGTH); + end "-"; + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) - R; + end "-"; + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L - TO_SIGNED(R, L'LENGTH); + end "-"; + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) - R; + end "-"; + + --============================================================================ + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable RESULT: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0) := (others => '0'); + variable ADVAL: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + ADVAL := RESIZE(XR, RESULT'LENGTH); + for I in 0 to L_LEFT loop + if XL(I)='1' then RESULT := RESULT + ADVAL; + end if; + ADVAL := SHIFT_LEFT(ADVAL, 1); + end loop; + return RESULT; + end "*"; + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + variable XL: SIGNED(L_LEFT downto 0); + variable XR: SIGNED(R_LEFT downto 0); + variable RESULT: SIGNED((L_LEFT+R_LEFT+1) downto 0) := (others => '0'); + variable ADVAL: SIGNED((L_LEFT+R_LEFT+1) downto 0); + begin + if ((L_LEFT < 0) or (R_LEFT < 0)) then return NAS; + end if; + XL := L; + XR := R; + ADVAL := RESIZE(XR, RESULT'LENGTH); + for I in 0 to L_LEFT-1 loop + if XL(I)='1' then RESULT := RESULT + ADVAL; + end if; + ADVAL := SHIFT_LEFT(ADVAL, 1); + end loop; + if XL(L_LEFT)='1' then + RESULT := RESULT - ADVAL; + end if; + return RESULT; + end "*"; + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L * TO_UNSIGNED(R, L'LENGTH); + end "*"; + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) * R; + end "*"; + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L * TO_SIGNED(R, L'LENGTH); + end "*"; + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) * R; + end "*"; + + --============================================================================ + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FQUOT; + end "/"; + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable QNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + QNEG := TRUE; + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + QNEG := not QNEG; + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if QNEG then FQUOT := "0"-FQUOT; + end if; + return SIGNED(FQUOT); + end "/"; + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, QUOT: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + if (R_LENGTH > L'LENGTH) then + QUOT := (others => '0'); + return RESIZE(QUOT, L'LENGTH); + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + QUOT := RESIZE((L / XR), QUOT'LENGTH); + return RESIZE(QUOT, L'LENGTH); + end "/"; + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, QUOT: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + QUOT := RESIZE((XL / R), QUOT'LENGTH); + if L_LENGTH > R'LENGTH + and QUOT(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""/"": Quotient Truncated" + severity WARNING; + end if; + return RESIZE(QUOT, R'LENGTH); + end "/"; + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, QUOT: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + if (R_LENGTH > L'LENGTH) then + QUOT := (others => '0'); + return RESIZE(QUOT, L'LENGTH); + end if; + XR := TO_SIGNED(R, R_LENGTH); + QUOT := RESIZE((L / XR), QUOT'LENGTH); + return RESIZE(QUOT, L'LENGTH); + end "/"; + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, QUOT: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + QUOT := RESIZE((XL / R), QUOT'LENGTH); + if L_LENGTH > R'LENGTH and QUOT(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => QUOT(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""/"": Quotient Truncated" + severity WARNING; + end if; + return RESIZE(QUOT, R'LENGTH); + end "/"; + + --============================================================================ + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FREMAIN; + end "rem"; + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable RNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + RNEG := TRUE; + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if RNEG then + FREMAIN := "0"-FREMAIN; + end if; + return SIGNED(FREMAIN); + end "rem"; + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, XREM: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + XREM := RESIZE((L rem XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "rem"; + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + XREM := RESIZE((XL rem R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "rem"; + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, XREM: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + XR := TO_SIGNED(R, R_LENGTH); + XREM := RESIZE((L rem XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => XREM(L'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "rem"; + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + XREM := RESIZE((XL rem R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => XREM(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "rem"; + + --============================================================================ + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FREMAIN; + end "mod"; + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable RNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + RNEG := TRUE; + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if RNEG and L(L'LEFT)='1' then + FREMAIN := "0"-FREMAIN; + elsif RNEG and FREMAIN/="0" then + FREMAIN := FREMAIN-XDENOM; + elsif L(L'LEFT)='1' and FREMAIN/="0" then + FREMAIN := XDENOM-FREMAIN; + end if; + return SIGNED(FREMAIN); + end "mod"; + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, XREM: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + XREM := RESIZE((L mod XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "mod"; + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + XREM := RESIZE((XL mod R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "mod"; + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, XREM: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + XR := TO_SIGNED(R, R_LENGTH); + XREM := RESIZE((L mod XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => XREM(L'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "mod"; + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + XREM := RESIZE((XL mod R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => XREM(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "mod"; + + --============================================================================ + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">"; + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not SIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">"; + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end ">"; + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not SIGNED_LESS_OR_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end ">"; + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end ">"; + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not SIGNED_LESS_OR_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end ">"; + + --============================================================================ + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<"; + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<"; + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return UNSIGNED_LESS(TO_UNSIGNED(L, R'LENGTH), R); + end "<"; + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return SIGNED_LESS(TO_SIGNED(L, R'LENGTH), R); + end "<"; + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return UNSIGNED_LESS(L, TO_UNSIGNED(R, L'LENGTH)); + end "<"; + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return SIGNED_LESS(L, TO_SIGNED(R, L'LENGTH)); + end "<"; + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<="; + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<="; + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return UNSIGNED_LESS_OR_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end "<="; + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return SIGNED_LESS_OR_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end "<="; + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return UNSIGNED_LESS_OR_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end "<="; + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return SIGNED_LESS_OR_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end "<="; + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not UNSIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">="; + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not SIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">="; + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not UNSIGNED_LESS(TO_UNSIGNED(L, R'LENGTH), R); + end ">="; + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not SIGNED_LESS(TO_SIGNED(L, R'LENGTH), R); + end ">="; + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not UNSIGNED_LESS(L, TO_UNSIGNED(R, L'LENGTH)); + end ">="; + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not SIGNED_LESS(L, TO_SIGNED(R, L'LENGTH)); + end ">="; + + --============================================================================ + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "="; + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "="; + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return FALSE; + end if; + return UNSIGNED_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end "="; + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return FALSE; + end if; + return SIGNED_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end "="; + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return UNSIGNED_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end "="; + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return SIGNED_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end "="; + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + return not(UNSIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE))); + end "/="; + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + return not(SIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE))); + end "/="; + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not(UNSIGNED_EQUAL(TO_UNSIGNED(L, R'LENGTH), R)); + end "/="; + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not(SIGNED_EQUAL(TO_SIGNED(L, R'LENGTH), R)); + end "/="; + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return TRUE; + end if; + return not(UNSIGNED_EQUAL(L, TO_UNSIGNED(R, L'LENGTH))); + end "/="; + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return TRUE; + end if; + return not(SIGNED_EQUAL(L, TO_SIGNED(R, L'LENGTH))); + end "/="; + + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XSLL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_LEFT; + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XSRL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_RIGHT; + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XSLL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_LEFT; + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XSRA(BIT_VECTOR(ARG), COUNT)); + end SHIFT_RIGHT; + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XROL(BIT_VECTOR(ARG), COUNT)); + end ROTATE_LEFT; + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XROR(BIT_VECTOR(ARG), COUNT)); + end ROTATE_RIGHT; + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XROL(BIT_VECTOR(ARG), COUNT)); + end ROTATE_LEFT; + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XROR(BIT_VECTOR(ARG), COUNT)); + end ROTATE_RIGHT; + + --============================================================================ + + ------------------------------------------------------------------------------ + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end "sll"; + + ------------------------------------------------------------------------------ + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), -COUNT)); + end if; + end "sll"; + + ------------------------------------------------------------------------------ + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(ARG, COUNT); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end "srl"; + + ------------------------------------------------------------------------------ + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end "srl"; + + ------------------------------------------------------------------------------ + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end "rol"; + + ------------------------------------------------------------------------------ + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end "rol"; + + ------------------------------------------------------------------------------ + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end "ror"; + + ------------------------------------------------------------------------------ + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end "ror"; + + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: NATURAL := 0; + begin + if (ARG'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.TO_INTEGER: null detected, returning 0" + severity WARNING; + return 0; + end if; + for I in XARG'RANGE loop + RESULT := RESULT+RESULT; + if XARG(I) = '1' then + RESULT := RESULT + 1; + end if; + end loop; + return RESULT; + end TO_INTEGER; + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER is + begin + if (ARG'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.TO_INTEGER: null detected, returning 0" + severity WARNING; + return 0; + end if; + if ARG(ARG'LEFT) = '0' then + return TO_INTEGER(UNSIGNED(ARG)); + else + return (- (TO_INTEGER(UNSIGNED(- (ARG + 1)))) -1); + end if; + end TO_INTEGER; + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED is + variable RESULT: UNSIGNED(SIZE-1 downto 0); + variable I_VAL: NATURAL := ARG; + begin + if (SIZE < 1) then return NAU; + end if; + for I in 0 to RESULT'LEFT loop + if (I_VAL mod 2) = 0 then + RESULT(I) := '0'; + else RESULT(I) := '1'; + end if; + I_VAL := I_VAL/2; + end loop; + if not(I_VAL =0) then + assert NO_WARNING + report "NUMERIC_BIT.TO_UNSIGNED: vector truncated" + severity WARNING; + end if; + return RESULT; + end TO_UNSIGNED; + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; + SIZE: NATURAL) return SIGNED is + variable RESULT: SIGNED(SIZE-1 downto 0); + variable B_VAL: BIT := '0'; + variable I_VAL: INTEGER := ARG; + begin + if (SIZE < 1) then return NAS; + end if; + if (ARG < 0) then + B_VAL := '1'; + I_VAL := -(ARG+1); + end if; + for I in 0 to RESULT'LEFT loop + if (I_VAL mod 2) = 0 then + RESULT(I) := B_VAL; + else + RESULT(I) := not B_VAL; + end if; + I_VAL := I_VAL/2; + end loop; + if ((I_VAL/=0) or (B_VAL/=RESULT(RESULT'LEFT))) then + assert NO_WARNING + report "NUMERIC_BIT.TO_SIGNED: vector truncated" + severity WARNING; + end if; + return RESULT; + end TO_SIGNED; + + --============================================================================ + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED is + alias INVEC: SIGNED(ARG'LENGTH-1 downto 0) is ARG; + variable RESULT: SIGNED(NEW_SIZE-1 downto 0) := (others => '0'); + constant BOUND: INTEGER := MIN(ARG'LENGTH, RESULT'LENGTH)-2; + begin + if (NEW_SIZE < 1) then return NAS; + end if; + if (ARG'LENGTH = 0) then return RESULT; + end if; + RESULT := (others => ARG(ARG'LEFT)); + if BOUND >= 0 then + RESULT(BOUND downto 0) := INVEC(BOUND downto 0); + end if; + return RESULT; + end RESIZE; + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: UNSIGNED(NEW_SIZE-1 downto 0) := (others => '0'); + begin + if (NEW_SIZE < 1) then return NAU; + end if; + if XARG'LENGTH =0 then return RESULT; + end if; + if (RESULT'LENGTH < ARG'LENGTH) then + RESULT(RESULT'LEFT downto 0) := XARG(RESULT'LEFT downto 0); + else + RESULT(RESULT'LEFT downto XARG'LEFT+1) := (others => '0'); + RESULT(XARG'LEFT downto 0) := XARG; + end if; + return RESULT; + end RESIZE; + + --============================================================================ + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(not(BIT_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) and BIT_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) or BIT_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) nand BIT_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) nor BIT_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) xor BIT_VECTOR(R)); + return RESULT; + end "xor"; + + ------------------------------------------------------------------------------ + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) xnor BIT_VECTOR(R)); + return RESULT; + end "xnor"; + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(not(BIT_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) and BIT_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) or BIT_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) nand BIT_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) nor BIT_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) xor BIT_VECTOR(R)); + return RESULT; + end "xor"; + + ------------------------------------------------------------------------------ + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) xnor BIT_VECTOR(R)); + return RESULT; + end "xnor"; + + --============================================================================ + + -- Id: E.1 + function RISING_EDGE (signal S: BIT) return BOOLEAN is + begin + return S'EVENT and S = '1'; + end RISING_EDGE; + + -- Id: E.2 + function FALLING_EDGE (signal S: BIT) return BOOLEAN is + begin + return S'EVENT and S = '0'; + end FALLING_EDGE; + + --============================================================================ +end NUMERIC_BIT; diff --git a/lib/Standard/ieee/numeric_std.vhdl b/lib/Standard/ieee/numeric_std.vhdl new file mode 100644 index 0000000..471a78c --- /dev/null +++ b/lib/Standard/ieee/numeric_std.vhdl @@ -0,0 +1,853 @@ +-- -------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +--This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +--as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_STD) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type STD_LOGIC. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_STD. The NUMERIC_STD package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- +-- -------------------------------------------------------------------- +-- modification history : +-- -------------------------------------------------------------------- +-- Version: 2.4 +-- Date : 12 April 1995 +-- ---------------------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.all; + +package NUMERIC_STD is + constant CopyRightNotice: STRING + := "Copyright 1995 IEEE. All rights reserved."; + + --=========================================================================== + -- Numeric array type definitions + --=========================================================================== + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector ARG. + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --=========================================================================== + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L(may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --=========================================================================== + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" (L: UNSIGNED;R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --=========================================================================== + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'LENGTH before multiplication. + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of SIZE L'LENGTH before + -- multiplication. + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of SIZE R'LENGTH before + -- multiplication. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --=========================================================================== + -- Comparison Operators + --=========================================================================== + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --=========================================================================== + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --=========================================================================== + -- Shift and Rotate Functions + --=========================================================================== + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT rightmost elements are lost. + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- The vacated positions are filled with '0'. + -- The COUNT leftmost elements are lost. + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost + -- element, ARG'LEFT. The COUNT rightmost elements are lost. + + --=========================================================================== + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED + -- vector COUNT times. + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED + -- vector COUNT times. + + --=========================================================================== + + --=========================================================================== + + ----------------------------------------------------------------------------- + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)) + + ----------------------------------------------------------------------------- + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + ----------------------------------------------------------------------------- + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ----------------------------------------------------------------------------- + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + --=========================================================================== + -- RESIZE Functions + --=========================================================================== + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + --=========================================================================== + -- Conversion Functions + --=========================================================================== + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified SIZE. + + --=========================================================================== + -- Logical Operators + --=========================================================================== + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + -- -------------------------------------------------------------------------- + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + -- -------------------------------------------------------------------------- + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + -- --------------------------------------------------------------------------- + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + -- --------------------------------------------------------------------------- + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + --=========================================================================== + -- Match Functions + --=========================================================================== + + -- Id: M.1 + function STD_MATCH (L, R: STD_ULOGIC) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.2 + function STD_MATCH (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.3 + function STD_MATCH (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.4 + function STD_MATCH (L, R: STD_LOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.5 + function STD_MATCH (L, R: STD_ULOGIC_VECTOR) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: terms compared per STD_LOGIC_1164 intent + + --=========================================================================== + -- Translation Functions + --=========================================================================== + + -- Id: T.1 + function TO_01 (S: UNSIGNED; XMAP: STD_LOGIC := '0') return UNSIGNED; + -- Result subtype: UNSIGNED(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. + + -- Id: T.2 + function TO_01 (S: SIGNED; XMAP: STD_LOGIC := '0') return SIGNED; + -- Result subtype: SIGNED(S'RANGE) + -- Result: Termwise, 'H' is translated to '1', and 'L' is translated + -- to '0'. If a value other than '0'|'1'|'H'|'L' is found, + -- the array is set to (others => XMAP), and a warning is + -- issued. + +end NUMERIC_STD; diff --git a/lib/Standard/ieee/numeric_std_body.vhd b/lib/Standard/ieee/numeric_std_body.vhd new file mode 100644 index 0000000..65dde0a --- /dev/null +++ b/lib/Standard/ieee/numeric_std_body.vhd @@ -0,0 +1,2671 @@ +-- ---------------------------------------------------------------------------- +-- Title : NUMERIC_STD arithmetic package for synthesis +-- : Rev. 1.7 (Nov. 23 1994) +-- : +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- : +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- : +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : --> UNSIGNED : represents UNSIGNED number in vector form +-- : --> SIGNED : represents a SIGNED number in vector form +-- : The base element type is type STD_LOGIC. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- : +-- Note : No declarations or definitions shall be included in, or +-- : excluded from, this package. The package declaration declares +-- : the functions that can be used by a user. The package body +-- : shall be considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement the +-- : package body in the most efficient manner available to them. +-- : +-- ---------------------------------------------------------------------------- +library ieee; +use ieee.STD_LOGIC_1164.all; + +Package numeric_std is + + --=========================================================================== + -- Numeric array type definitions + --=========================================================================== + + type UNSIGNED is array ( NATURAL range <> ) of STD_LOGIC; + type SIGNED is array ( NATURAL range <> ) of STD_LOGIC; + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + + -- Id: A.1 + function "abs" ( X : SIGNED) return SIGNED; + -- Result subtype: SIGNED(X'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector X. + + -- Id: A.2 + function "-" ( ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --============================================================================ + + -- Id: A.3 + function "+" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED (R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L (may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED (L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" ( L: UNSIGNED;R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED (L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED((L'length+R'length-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'length+R'length-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'length+L'length-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'length before multiplication. + + -- Id: A.18 + function "*" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'length+R'length-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'length before multiplication. + + -- Id: A.19 + function "*" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'length+L'length-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of SIZE L'length before + -- multiplication. + + -- Id: A.20 + function "*" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'length+R'length-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of SIZE R'length before + -- multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED (L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED (L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.24 + function "/" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED (R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + -- Id: A.25 + function "/" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED (L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.26 + function "/" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED (R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function shift_left ( ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits are lost. + + -- Id: S.2 + function shift_right ( ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT rightmost bits are lost. + + -- Id: S.3 + function shift_left ( ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- All bits of ARG, except ARG'LEFT, are shifted left COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits, except ARG'LEFT, are lost. + + -- Id: S.4 + function shift_right ( ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost bit,ARG'LEFT. + -- The COUNT rightmost bits are lost. + + --============================================================================ + + --============================================================================ + + -- Id: S.5 + function rotate_left ( ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate_left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function rotate_right ( ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate_right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function rotate_left ( ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED + -- vector COUNT times. + + -- Id: S.8 + function rotate_right ( ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED + -- vector COUNT times. + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.1 + function RESIZE ( ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ReSIZEs the SIGNED vector ARG to the specified SIZE. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE ( ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ReSIZEs the SIGNED vector ARG to the specified SIZE. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER ( ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER ( ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED ( ARG,SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. + + -- Id: D.4 + function TO_SIGNED ( ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED (SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified SIZE. + + -- Id: D.5 + function TO_UNSIGNED ( ARG: STD_LOGIC_VECTOR) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input ARG + -- Result: Converts STD_LOGIC_VECTOR to UNSIGNED. + + -- Id: D.6 + function TO_SIGNED ( ARG: STD_LOGIC_VECTOR) return SIGNED; + -- Result subtype: SIGNED, same range as input ARG + -- Result: Converts STD_LOGIC_VECTOR to SIGNED. + + -- Id: D.7 + function TO_STDLOGICVECTOR ( ARG: UNSIGNED) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR, same range as input ARG + -- Result: Converts UNSIGNED to STD_LOGIC_VECTOR. + + -- Id: D.8 + function TO_STDLOGICVECTOR ( ARG: SIGNED) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR, same range as input ARG + -- Result: Converts SIGNED to STD_LOGIC_VECTOR. + + --============================================================================ + -- Logical Operators + --============================================================================ + + -- Id: L.1 + function "not" ( L: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Termwise inversion + + -- Id: L.2 + function "and" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector AND operation + + -- Id: L.3 + function "or" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector XOR operation + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this 1076.3 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + -- Id: L.7 +-- function "xnor" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" ( L: SIGNED) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Termwise inversion + + -- Id: L.9 + function "and" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector AND operation + + -- Id: L.10 + function "or" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector XOR operation + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this 1076.3 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + -- Id: L.14 +-- function "xnor" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector XNOR operation + + --============================================================================ + -- Match Functions + --============================================================================ + + -- Id: M.1 + function STD_MATCH (L, R: STD_ULOGIC) return BOOLEAN; + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.2 + function STD_MATCH (L, R: STD_LOGIC_VECTOR) return BOOLEAN; + -- Result: termwise comparison per STD_LOGIC_1164 intent + + end numeric_std; + +--============================================================================= +--======================= Package Body =============================== +--============================================================================= + + +Package body numeric_std is + + + -- null range array constants + +constant NAU : UNSIGNED (0 downto 1) := (others => '0'); +constant NAS : SIGNED (0 downto 1) := (others => '0'); + + -- implementation controls + +constant NO_WARNING : boolean := FALSE; -- default to emit warnings + +--=========================Local Subprograms================================= + +function MAX(LEFT, RIGHT: INTEGER) return INTEGER is +begin + if LEFT > RIGHT then return LEFT; + else return RIGHT; + end if; + end; + +function MIN(LEFT, RIGHT: INTEGER) return INTEGER is +begin + if LEFT < RIGHT then return LEFT; + else return RIGHT; + end if; + end; + +function Signed_NUM_BITS ( ARG: INTEGER) return natural is +variable nBits: natural; +variable N: natural; +begin + if ARG>=0 then + N:=ARG; + else + N:=-(ARG+1); + end if; + nBits:=1; + while N>0 loop + nBits:=nBits+1; + N:= N / 2; + end loop; + return nBits; + end; + +function UNSIGNED_NUM_BITS (ARG: natural) return natural is +variable nBits: natural; +variable N: natural; +begin + N:=ARG; + nBits:=1; + while N>1 loop + nBits:=nBits+1; + N:= N / 2; + end loop; + return nBits; + end; + + +------------------------------------------------------------------------ + + -- this internal function computes the addition of two UNSIGNED + -- with input CARRY + -- * the two arguments are of the same length + +function ADD_UNSIGNED ( L,R: UNSIGNED; C: STD_LOGIC ) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(L_left downto 0) is R; +variable RESULT: UNSIGNED(L_left downto 0); +variable CBIT : STD_LOGIC:= C; +begin + for i in 0 to L_left loop + RESULT(i) := CBIT xor XL(i) xor XR(i); + CBIT := (CBIT and XL(i)) or (CBIT and XR(i)) or (XL(i) and XR(i)); + end loop; + return RESULT; + end ADD_UNSIGNED; + + -- this internal function computes the addition of two SIGNED + -- with input CARRY + -- * the two arguments are of the same length + +function ADD_SIGNED ( L,R: SIGNED; C: STD_LOGIC ) return SIGNED is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(L_left downto 0) is R; +variable RESULT: SIGNED(L_left downto 0); +variable CBIT: STD_LOGIC:= C; +begin + for i in 0 to L_left loop + RESULT(i) := CBIT xor XL(i) xor XR(i); + CBIT := (CBIT and XL(i)) or (CBIT and XR(i)) or (XL(i) and XR(i)); + end loop; + return RESULT; + end ADD_SIGNED; + +------------------------------------------------------------------------ + + -- this internal procedure computes UNSIGNED division + -- giving the quotient and remainder. + procedure divMod (num, XDENOM: UNSIGNED; + xquot, xremain: out UNSIGNED) is + variable TEMP: UNSIGNED(num'length-1 downto 0); + variable quot: UNSIGNED(MAX(num'length,XDENOM'length)-1 downto 0); + variable diff: UNSIGNED(XDENOM'length downto 0); + alias DENOM : UNSIGNED (XDENOM'length-1 downto 0) is XDENOM; + variable CARRY: STD_LOGIC; + variable TOPBIT: natural; + variable isZero: boolean; + begin + isZero:=TRUE; + for j in XDENOM'range loop + CARRY:=DENOM(j); + if CARRY/='0' then + isZero:=FALSE; + end if; + end loop; + assert not isZero + report "DIV,MOD,or REM by zero" + severity error; + TEMP:=num; + quot:= (others =>'0'); + TOPBIT:=0; + for j in DENOM'range loop + if DENOM(j)='1' then + TOPBIT:=j; + exit; + end if; + end loop; + + CARRY:='0'; + for j in num'length-(TOPBIT+1) downto 0 loop + -- lexical ordering works okay for this comparison, no overloaded + -- function is needed. + if CARRY&TEMP(TOPBIT+j downto j) >= "0"&DENOM(TOPBIT downto 0) then + diff(TOPBIT+1 downto 0) := (CARRY&TEMP(TOPBIT+j downto j)) + -("0"&DENOM(TOPBIT downto 0)); + + assert diff(TOPBIT+1)='0' + report "internal error in the division algorithm" + severity error; + CARRY:=diff(TOPBIT); + if TOPBIT+j+1<=TEMP'left then + TEMP(TOPBIT+j+1):='0'; + end if; + TEMP(TOPBIT+j downto j):=diff(TOPBIT downto 0); + quot(j):='1'; + else + assert CARRY='0' + report "internal error in the division algorithm" + severity error; + CARRY:=TEMP(TOPBIT+j); + end if; + end loop; + xquot:=quot(num'length-1 downto 0); + xremain:=TEMP(num'length-1 downto 0); + end divMod; + +-----------------Local Subprograms - shift/rotate ops------------------------- + +function XSLL(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := (others=>'0'); +begin + if COUNT <= ARG_L then + RESULT(ARG_L downto COUNT):=XARG(ARG_L-COUNT downto 0); + end if; + return RESULT; +end; + +function XSRL(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := (others=>'0'); +begin + if COUNT <= ARG_L then + RESULT(ARG_L-COUNT downto 0):=XARG(ARG_L downto COUNT); + end if; + return RESULT; +end; + +function XSRA(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0); +variable XCOUNT: natural := COUNT; +begin + if ((ARG'length <= 1) or (xCOUNT = 0)) then return ARG; + else + if (XCOUNT > ARG_L) then xCOUNT:= ARG_L; end if; + RESULT(ARG_L-XCOUNT downto 0):=XARG(ARG_L downto XCOUNT); + RESULT(ARG_L downto (ARG_L - XCOUNT + 1)) := (others=>XARG(ARG_L)); + end if; + return RESULT; + end; + +function XROL(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := XARG; +variable COUNTM: INTEGER; +begin + COUNTM:= COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L downto COUNTM):=XARG(ARG_L-COUNTM downto 0); + RESULT(COUNTM-1 downto 0):=XARG(ARG_L downto ARG_L-COUNTM+1); + end if; + return RESULT; + end; + +function XROR(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := XARG; +variable COUNTM: INTEGER; +begin + COUNTM:= COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L-COUNTM downto 0):=XARG(ARG_L downto COUNTM); + RESULT(ARG_L downto ARG_L-COUNTM+1):=XARG(COUNTM-1 downto 0); + end if; + return RESULT; + end; + + +-----------------Local Subprograms - Relational ops-------------------------- + +-- +-- General "=" for UNSIGNED vectors, same length +-- +function UNSIGNED_equal ( L,R: UNSIGNED) return BOOLEAN is +begin + return STD_LOGIC_VECTOR (L) = STD_LOGIC_VECTOR (R) ; + end; + +-- +-- General "=" for SIGNED vectors, same length +-- +function SIGNED_equal ( L,R: SIGNED) return BOOLEAN is +begin + return STD_LOGIC_VECTOR (L) = STD_LOGIC_VECTOR (R) ; + end; + + + +-- +-- General "<" for UNSIGNED vectors, same length +-- +function UNSIGNED_LESS ( L,R: UNSIGNED) return BOOLEAN is +begin + return STD_LOGIC_VECTOR (L) < STD_LOGIC_VECTOR (R) ; + end UNSIGNED_LESS ; + +-- +-- General "<" function for SIGNED vectors, same length +-- +function SIGNED_LESS ( L,R: SIGNED) return BOOLEAN is +variable intern_l : SIGNED (0 to L'LENGTH-1); +variable intern_r : SIGNED (0 to R'LENGTH-1); +begin + intern_l:=l; + intern_r:=r; + intern_l(0):=not intern_l(0); + intern_r(0):=not intern_r(0); + return STD_LOGIC_VECTOR (intern_L) < STD_LOGIC_VECTOR (intern_R) ; +end; + +-- +-- General "<=" function for UNSIGNED vectors, same length +-- +function UNSIGNED_LESS_OR_EQUAL ( L,R: UNSIGNED) return BOOLEAN is +begin + return STD_LOGIC_VECTOR (L) <= STD_LOGIC_VECTOR (R) ; + end; + +-- +-- General "<=" function for SIGNED vectors, same length +-- +function SIGNED_LESS_OR_EQUAL ( L,R: SIGNED) return BOOLEAN is + -- Need aliasses to assure index direction +variable intern_l : SIGNED (0 to L'LENGTH-1); +variable intern_r : SIGNED (0 to R'LENGTH-1); +begin + intern_l:=l; + intern_r:=r; + intern_l(0):=not intern_l(0); + intern_r(0):=not intern_r(0); + return STD_LOGIC_VECTOR (intern_L) <= STD_LOGIC_VECTOR (intern_R) ; + end; + +-- function TO_01 is used to convert vectors to the +-- correct form for exported functions, +-- and to report if there is an element which +-- is not in (0,1,h,l). +-- Assume the vector is normalized and non-null. +-- The function is duplicated for SIGNED and UNSIGNED types. + +function TO_01(S : SIGNED ; xmap : STD_LOGIC:= '0') return SIGNED is +variable RESULT: SIGNED(S'length-1 downto 0); +variable bad_element : boolean := FALSE; +alias xs : SIGNED(s'length-1 downto 0) is S; +begin + for i in RESULT'range loop + case xs(i) is + when '0' | 'L' => RESULT(i):='0'; + when '1' | 'H' => RESULT(i):='1'; + when others => bad_element := TRUE; + end case; + end loop; + if bad_element then + assert NO_WARNING + report "numeric_std.TO_01: Array Element not in {0,1,H,L}" + severity warning; + for i in RESULT'range loop + RESULT(i) := xmap; -- standard fixup + end loop; + end if; + return RESULT; + end TO_01; + +function TO_01(S : UNSIGNED ; xmap : STD_LOGIC:= '0') return UNSIGNED is +variable RESULT: UNSIGNED(S'length-1 downto 0); +variable bad_element : boolean := FALSE; +alias xs : UNSIGNED(S'length-1 downto 0) is S; +begin + for i in RESULT'range loop + case xs(i) is + when '0' | 'L' => RESULT(i):='0'; + when '1' | 'H' => RESULT(i):='1'; + when others => bad_element := TRUE; + end case; + end loop; + if bad_element then + assert NO_WARNING + report "numeric_std.TO_01: Array Element not in {0,1,H,L}" + severity warning; + for i in RESULT'range loop + RESULT(i) := xmap; -- standard fixup + end loop; + end if; + return RESULT; + end TO_01; + +--=========================Exported Functions================================= + + -- Id: A.1 +function "abs" ( X : SIGNED) return SIGNED is +constant ARG_LEFT:INTEGER:= X'length-1; +alias XX : SIGNED(ARG_LEFT downto 0) is X; +variable RESULT: SIGNED (ARG_LEFT downto 0); +begin + if X'length<1 then return NAS; end if; + RESULT:=TO_01(xx,'X'); + if (RESULT(RESULT'left)='X') then return RESULT; end if; + if RESULT(RESULT'left) = '1' then + RESULT:= -RESULT; + end if; + return RESULT; + end; -- "abs" + + + -- Id: A.2 +function "-" ( ARG: SIGNED) return SIGNED is +constant ARG_LEFT:INTEGER:= ARG'length-1; +alias XARG: SIGNED(ARG_LEFT downto 0) is ARG; +variable RESULT,XARG01 : SIGNED(ARG_LEFT downto 0); +variable CBIT : STD_LOGIC:= '1'; +begin + if ARG'length<1 then return NAS; end if; + XARG01 := TO_01(ARG,'X'); + if (XARG01(XARG01'left)='X') then return XARG01; end if; + for i in 0 to RESULT'left loop + RESULT(i) := not(XARG01(i)) xor CBIT; + CBIT := CBIT and not(XARG01(i)); + end loop; + return RESULT; + end; -- "-" + + +--============================================================================= + + + -- Id: A.3 +function "+" ( L,R: UNSIGNED ) return UNSIGNED is +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(SIZE-1 downto 0); +variable R01 : UNSIGNED(SIZE-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + L01 := TO_01(RESIZE(L,SIZE),'X'); + if (L01(L01'left)='X') then return L01; end if; + R01 := TO_01(RESIZE(R,SIZE),'X'); + if (R01(R01'left)='X') then return R01; end if; + return ADD_UNSIGNED (L01, R01, '0') ; + end; + + -- Id: A.4 +function "+" ( L,R: SIGNED ) return SIGNED is +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(SIZE-1 downto 0); +variable R01 : SIGNED(SIZE-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + L01 := TO_01(RESIZE(L,SIZE),'X'); + if (L01(L01'left)='X') then return L01; end if; + R01 := TO_01(RESIZE(R,SIZE),'X'); + if (R01(R01'left)='X') then return R01; end if; + return ADD_SIGNED (L01, R01, '0') ; + end; + + -- Id: A.5 +function "+" ( L: UNSIGNED; R: NATURAL) return UNSIGNED is +begin + return L + TO_UNSIGNED( R , L'length); + end; + + -- Id: A.6 +function "+" ( L: NATURAL; R: UNSIGNED) return UNSIGNED is +begin + return TO_UNSIGNED( L , R'length) + R; + end; + + -- Id: A.7 +function "+" ( L: SIGNED; R: INTEGER) return SIGNED is +begin + return L + TO_SIGNED( R , L'length); + end; + + -- Id: A.8 +function "+" ( L: INTEGER; R: SIGNED) return SIGNED is +begin + return TO_SIGNED( L , R'length) + R; + end; + +--============================================================================= + + -- Id: A.9 +function "-" ( L,R: UNSIGNED) return UNSIGNED is +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(SIZE-1 downto 0); +variable R01 : UNSIGNED(SIZE-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + L01 := TO_01(RESIZE(L,SIZE),'X'); + if (L01(L01'left)='X') then return L01; end if; + R01 := TO_01(RESIZE(R,SIZE),'X'); + if (R01(R01'left)='X') then return R01; end if; + return ADD_UNSIGNED (L01,not(R01),'1'); + end; + + -- Id: A.10 +function "-" ( L,R: SIGNED) return SIGNED is +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(SIZE-1 downto 0); +variable R01 : SIGNED(SIZE-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + L01 := TO_01(RESIZE(L,SIZE),'X'); + if (L01(L01'left)='X') then return L01; end if; + R01 := TO_01(RESIZE(R,SIZE),'X'); + if (R01(R01'left)='X') then return R01; end if; + return ADD_SIGNED (L01,not(R01),'1'); + end; + + + + -- Id: A.11 +function "-" ( L: UNSIGNED; R: NATURAL) return UNSIGNED is +begin + return L - TO_UNSIGNED( R , L'length); + end; + + -- Id: A.12 +function "-" ( L: NATURAL; R: UNSIGNED) return UNSIGNED is +begin + return TO_UNSIGNED( L , R'length) - R; + end; + + -- Id: A.13 +function "-" ( L: SIGNED; R: INTEGER) return SIGNED is +begin + return L - TO_SIGNED( R , L'length); + end; + + -- Id: A.14 +function "-" ( L: INTEGER; R: SIGNED) return SIGNED is +begin + return TO_SIGNED( L , R'length) - R ; + end; + + +--============================================================================= + + -- Id: A.15 +function "*" ( L,R: UNSIGNED) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : UNSIGNED(L_left downto 0) is L; +alias xxr : UNSIGNED(R_left downto 0) is R; +variable xl : UNSIGNED(L_left downto 0); +variable xr : UNSIGNED(R_left downto 0); +variable RESULT: UNSIGNED((L'length+R'length-1) downto 0) :=(others=>'0'); +variable adval : UNSIGNED((L'length+R'length-1) downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + RESULT:= (others=>'X'); + return RESULT; + end if; + adval := RESIZE(xr,RESULT'length); + for i in 0 to L_left loop + if xl(i)='1' then RESULT:= RESULT + adval; + end if; + adval := shift_left(adval,1); + end loop; + return RESULT; +end; + + -- Id: A.16 +function "*" ( L,R: SIGNED) return SIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : SIGNED(L_left downto 0) is L; +alias xxr : SIGNED(R_left downto 0) is R; +variable xl : SIGNED(L_left downto 0); +variable xr : SIGNED(R_left downto 0); +variable RESULT: SIGNED((L'length+R'length-1) downto 0) :=(others=>'0'); +variable adval : SIGNED((L'length+R'length-1) downto 0); +variable invt : STD_LOGIC:= '0'; +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + RESULT:= (others=>'X'); + return RESULT; + end if; + adval := RESIZE(xr,RESULT'length); + if xl(xl'left)='1' then + adval := -(adval); + invt := '1'; + end if; + for i in 0 to L_left loop + if (invt xor xl(i))='1' then RESULT:= RESULT + adval; + end if; + adval := shift_left(adval,1); + end loop; + return RESULT; + end; + + + -- Id: A.17 +function "*" ( L: UNSIGNED; R: NATURAL) return UNSIGNED is +begin + return L * TO_UNSIGNED( R , L'length); + end; + + -- Id: A.18 +function "*" ( L: NATURAL; R: UNSIGNED) return UNSIGNED is +begin + return TO_UNSIGNED( L , R'length) * R; + end; + + -- Id: A.19 +function "*" ( L: SIGNED; R: INTEGER) return SIGNED is +begin + return L * TO_SIGNED( R , L'length); + end; + + -- Id: A.20 +function "*" ( L: INTEGER; R: SIGNED) return SIGNED is +begin + return TO_SIGNED( L , R'length) * R ; + end; + +--============================================================================= + + -- Id: A.21 +function "/" ( L,R: UNSIGNED) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : UNSIGNED(L_left downto 0) is L; +alias xxr : UNSIGNED(R_left downto 0) is R; +variable xl : UNSIGNED(L_left downto 0); +variable xr : UNSIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(L'length-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fquot := (others=>'X'); + return fquot; + end if; + divMod(xl,xr,fquot,fremain); + return fquot; + end; + + -- Id: A.22 +function "/" ( L,R: SIGNED) return SIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : SIGNED(L_left downto 0) is L; +alias xxr : SIGNED(R_left downto 0) is R; +variable xl : SIGNED(L_left downto 0); +variable xr : SIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(L'length-1 downto 0); +variable xnum: UNSIGNED(L'length-1 downto 0); +variable XDENOM: UNSIGNED(R'length-1 downto 0); +variable qneg: boolean := FALSE; +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fquot := (others=>'X'); + return SIGNED(fquot); + end if; + if xl(xl'left)='1' then + xnum:=UNSIGNED(-xl); + qNeg:=TRUE; + else + xnum:=UNSIGNED(xl); + end if; + if xr(xr'left)='1' then + xdenom:=UNSIGNED(-xr); + qNeg:=not qNeg; + else + xdenom:=UNSIGNED(xr); + end if; + divMod(xnum,XDENOM,fquot,fremain); + if qNeg then fquot:="0"-fquot; end if; + return SIGNED(fquot); + end; + + -- Id: A.23 +function "/" ( L : UNSIGNED; R : NATURAL) return UNSIGNED is + constant R_Length : Natural := max(L'Length, unsigned_num_bits(R)); + variable XR,Quot : unsigned (R_Length-1 downto 0); +begin + XR := TO_UNSIGNED(R, R_Length); + Quot := L / XR; + if R_Length>L'Length and Quot(0)/='X' + and Quot(R_Length-1 downto L'Length)/=(R_Length-1 downto L'Length => '0') + then + ASSERT no_warning report "Numeric_std.""/"": Quotient Truncated" + severity warning; + end if; + return Quot(L'Length-1 downto 0); + end; + + -- Id: A.24 +function "/" ( L : NATURAL; R : UNSIGNED) return UNSIGNED is + constant L_Length : Natural := max(unsigned_num_bits(L), R'length); + variable XL,Quot : UNSIGNED (L_Length-1 downto 0); +begin + XL := TO_UNSIGNED(L,L_LENGTH); + QUOT := XL / R; + if L_LENGTH>R'LENGTH and Quot(0)/='X' + and QUOT(L_LENGTH-1 downto R'Length)/=(L_LENGTH-1 downto R'Length => '0') + then + ASSERT no_warning report "Numeric_std.""/"": Quotient Truncated" + severity warning; + end if; + return Quot(R'Length-1 downto 0); + end; + + -- Id: A.25 +function "/" ( L : SIGNED; R : INTEGER ) return SIGNED is + constant R_Length : Natural := max(L'Length, signed_num_bits(R)); + variable XR,Quot : signed (R_Length-1 downto 0); +begin + XR := TO_SIGNED(R, R_Length); + Quot := L / XR; + if R_Length>L'Length and Quot(0)/='X' + and Quot(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => Quot(L'Length-1)) + then + ASSERT no_warning report "Numeric_std.""/"": Quotient Truncated" + severity warning; + end if; + return Quot(L'Length-1 downto 0); + end; + + -- Id: A.26 +function "/" ( L : INTEGER; R : SIGNED) return SIGNED is + constant L_Length : Natural := max(signed_num_bits(L), R'length); + variable XL,Quot : SIGNED (L_Length-1 downto 0); +begin + XL := TO_SIGNED(L,L_LENGTH); + QUOT := XL / R; + if L_LENGTH>R'LENGTH and Quot(0)/='X' + and QUOT(L_LENGTH-1 downto R'Length) + /= (L_LENGTH-1 downto R'Length => Quot(R'Length-1)) + then + ASSERT no_warning report "Numeric_std.""/"": Quotient Truncated" + severity warning; + end if; + return Quot(R'Length-1 downto 0); + end; +--============================================================================= + + -- Id: A.27 +function "rem" ( L,R: UNSIGNED) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : UNSIGNED(L_left downto 0) is L; +alias xxr : UNSIGNED(R_left downto 0) is R; +variable xl : UNSIGNED(L_left downto 0); +variable xr : UNSIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(l'length-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fremain := (others=>'X'); + return fremain; + end if; + divMod(xl,xr,fquot,fremain); + return fremain; + end; + + -- Id: A.28 +function "rem" ( L,R: SIGNED) return SIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : SIGNED(L_left downto 0) is L; +alias xxr : SIGNED(R_left downto 0) is R; +variable fquot,fremain : UNSIGNED(l'length-1 downto 0); +variable xnum: UNSIGNED(l'length-1 downto 0); +variable XDENOM: UNSIGNED(r'length-1 downto 0); +variable rneg: boolean := FALSE; +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + xnum := UNSIGNED(TO_01(xxl,'X')); + XDENOM := UNSIGNED(TO_01(xxr,'X')); + if ((xnum(xnum'left)='X') or (xdenom(xnum'left)='X')) then + fremain := (others=>'X'); + return SIGNED(fremain); + end if; + if xnum(xnum'left)='1' then + xnum:=UNSIGNED(-SIGNED(xnum)); + rNeg:=TRUE; + else + xNum:=UNSIGNED(xnum); + end if; + if XDENOM(XDENOM'left)='1' then + XDENOM:=UNSIGNED(-SIGNED(XDENOM)); + else + XDENOM:=UNSIGNED(XDENOM); + end if; + divMod(xnum,XDENOM,fquot,fremain); + if rNeg then + fremain:="0"-fremain; + end if; + return SIGNED(fremain); + end; + + -- Id: A.29 +function "rem" ( L : UNSIGNED; R : NATURAL) return UNSIGNED is + constant R_Length : Natural := max(L'Length, unsigned_num_bits(R)); + variable XR,XRem : unsigned (R_Length-1 downto 0); +begin + XR := TO_UNSIGNED(R, R_Length); + XRem := L rem XR; + if R_Length>L'Length and XRem(0)/='X' + and XRem(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => '0') + then + ASSERT no_warning report "Numeric_std.""rem"": Remainder Truncated" + severity warning; + end if; + return XRem(L'Length-1 downto 0); +end; + + -- Id: A.30 +function "rem" ( L : NATURAL; R : UNSIGNED) return UNSIGNED is + constant L_Length : Natural := max(unsigned_num_bits(L), R'Length); + variable XL,XRem : unsigned (L_Length-1 downto 0); +begin + XL := TO_UNSIGNED(L, L_Length); + XRem := XL rem R; + if L_Length>R'Length and XRem(0)/='X' + and XRem(L_Length-1 downto R'Length) + /= (L_Length-1 downto R'Length => '0') + then + ASSERT no_warning report "Numeric_std.""rem"": Remainder Truncated" + severity warning; + end if; + return XRem(R'Length-1 downto 0); +end; + + -- Id: A.31 +function "rem" ( L : SIGNED; R : INTEGER ) return SIGNED is + constant R_Length : Natural := max(L'Length, signed_num_bits(R)); + variable XR,XRem : signed (R_Length-1 downto 0); +begin + XR := TO_SIGNED(R, R_Length); + XRem := L rem XR; + if R_Length>L'Length and XRem(0)/='X' + and XRem(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => XRem(L'Length-1)) + then + ASSERT no_warning report "Numeric_std.""rem"": Remainder Truncated" + severity warning; + end if; + return XRem(L'Length-1 downto 0); +end; + + -- Id: A.32 +function "rem" ( L : INTEGER; R : SIGNED) return SIGNED is + constant L_Length : Natural := max(signed_num_bits(L), R'Length); + variable XL,XRem : signed (L_Length-1 downto 0); +begin + XL := TO_SIGNED(L, L_Length); + XRem := XL rem R; + if L_Length>R'Length and XRem(0)/='X' + and XRem(L_Length-1 downto R'Length) + /= (L_Length-1 downto R'Length => XRem(R'Length-1)) + then + ASSERT no_warning report "Numeric_std.""rem"": Remainder Truncated" + severity warning; + end if; + return XRem(R'Length-1 downto 0); +end; + +--============================================================================= + + -- Id: A.33 +function "mod" ( L,R: UNSIGNED) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : UNSIGNED(L_left downto 0) is L; +alias xxr : UNSIGNED(R_left downto 0) is R; +variable xl : UNSIGNED(L_left downto 0); +variable xr : UNSIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(l'length-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fremain := (others=>'X'); + return fremain; + end if; + divMod(xl,xr,fquot,fremain); + return fremain; + end; + + -- Id: A.34 +function "mod" ( L,R: SIGNED) return SIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : SIGNED(L_left downto 0) is L; +alias xxr : SIGNED(R_left downto 0) is R; +variable xl : SIGNED(L_left downto 0); +variable xr : SIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(l'length-1 downto 0); +variable xnum: UNSIGNED(l'length-1 downto 0); +variable XDENOM: UNSIGNED(r'length-1 downto 0); +variable rneg: boolean := FALSE; +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fremain := (others=>'X'); + return SIGNED(fremain); + end if; + if xl(xl'left)='1' then + xnum:=UNSIGNED(-xl); + else + xNum:=UNSIGNED(xl); + end if; + if xr(xr'left)='1' then + XDENOM:=UNSIGNED(-xr); + rNeg:=TRUE; + else + XDENOM:=UNSIGNED(xr); + end if; + divMod(xnum,XDENOM,fquot,fremain); + if rNeg and l(l'left)='1' then + fremain:="0"-fremain; + elsif rNeg then + fremain:=fremain-XDENOM; + elsif l(l'left)='1' then + fremain:=XDENOM-fremain; + end if; + return SIGNED(fremain); + end; + + -- Id: A.35 +function "mod" ( L : UNSIGNED; R : NATURAL) return UNSIGNED is + constant R_Length : Natural := max(L'Length, unsigned_num_bits(R)); + variable XR,XRem : unsigned (R_Length-1 downto 0); +begin + XR := TO_UNSIGNED(R, R_Length); + XRem := L mod XR; + if R_Length>L'Length and XRem(0)/='X' + and XRem(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => '0') + then + ASSERT no_warning report "Numeric_std.""mod"": Modulus Truncated" + severity warning; + end if; + return XRem(L'Length-1 downto 0); +end; + + -- Id: A.36 +function "mod" ( L : NATURAL; R : UNSIGNED) return UNSIGNED is + constant L_Length : Natural := max(unsigned_num_bits(L), R'Length); + variable XL,XRem : unsigned (L_Length-1 downto 0); +begin + XL := TO_UNSIGNED(L, L_Length); + XRem := XL mod R; + if L_Length>R'Length and XRem(0)/='X' + and XRem(L_Length-1 downto R'Length) + /= (L_Length-1 downto R'Length => '0') + then + ASSERT no_warning report "Numeric_std.""mod"": Modulus Truncated" + severity warning; + end if; + return XRem(R'Length-1 downto 0); +end; + + -- Id: A.37 +function "mod" ( L : SIGNED; R : INTEGER ) return SIGNED is + constant R_Length : Natural := max(L'Length, signed_num_bits(R)); + variable XR,XRem : signed (R_Length-1 downto 0); +begin + XR := TO_SIGNED(R, R_Length); + XRem := L mod XR; + if R_Length>L'Length and XRem(0)/='X' + and XRem(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => XRem(L'Length-1)) + then + ASSERT no_warning report "Numeric_std.""mod"": Modulus Truncated" + severity warning; + end if; + return XRem(L'Length-1 downto 0); +end; + + -- Id: A.38 +function "mod" ( L : INTEGER; R : SIGNED) return SIGNED is + constant L_Length : Natural := max(signed_num_bits(L), R'Length); + variable XL,XRem : signed (L_Length-1 downto 0); +begin + XL := TO_SIGNED(L, L_Length); + XRem := XL mod R; + if L_Length>R'Length and XRem(0)/='X' + and XRem(L_Length-1 downto R'Length) + /= (L_Length-1 downto R'Length => XRem(R'Length-1)) + then + ASSERT no_warning report "Numeric_std.""mod"": Modulus Truncated" + severity warning; + end if; + return XRem(R'Length-1 downto 0); +end; + +--============================================================================= + + -- Id: C.1 +function ">" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return not UNSIGNED_LESS_OR_EQUAL (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end ">" ; + + -- Id: C.2 +function ">" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return not SIGNED_LESS_OR_EQUAL (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end ">" ; + + -- Id: C.3 +function ">" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(l)>R'length then return TRUE; end if; + return not UNSIGNED_LESS_OR_EQUAL (TO_UNSIGNED (L,R01'LENGTH), R01) ; + end ">" ; + + -- Id: C.4 +function ">" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(l)>R'length then return L>0; end if; + return not SIGNED_LESS_OR_EQUAL (TO_SIGNED(L,R01'LENGTH), R01) ; + end ">" ; + + -- Id: C.5 +function ">" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return FALSE; end if; + return not UNSIGNED_LESS_OR_EQUAL (L01, TO_UNSIGNED (R,L01'LENGTH)) ; + end ">" ; + + -- Id: C.6 +function ">" ( L: SIGNED; R: INTEGER) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +variable L01 : SIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(R)>L'length then return 0>R; end if; + return not SIGNED_LESS_OR_EQUAL (L01, TO_SIGNED(R,L01'LENGTH)) ; + end ">" ; + +--============================================================================= + + -- Id: C.7 +function "<" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return UNSIGNED_LESS (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end "<" ; + + -- Id: C.8 +function "<" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return SIGNED_LESS (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end "<" ; + + -- Id: C.9 +function "<" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(L)>R'length then return L<0; end if; + return UNSIGNED_LESS (TO_UNSIGNED(L,R01'LENGTH), R01) ; + end "<" ; + + -- Id: C.10 +function "<" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(L)>R'length then return L<0; end if; + return SIGNED_LESS (TO_SIGNED(L,R01'LENGTH), R01) ; + end "<" ; + + -- Id: C.11 +function "<" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return 0L'length then return 0=" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return not UNSIGNED_LESS (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end ">=" ; + + -- Id: C.20 +function ">=" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return not SIGNED_LESS (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end ">=" ; + + -- Id: C.21 +function ">=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(L)>R'length then return L>0; end if; + return not UNSIGNED_LESS (TO_UNSIGNED(L,R01'LENGTH), R01) ; + end ">=" ; + + -- Id: C.22 +function ">=" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(L)>R'length then return L>0; end if; + return not SIGNED_LESS (TO_SIGNED (L,R01'LENGTH), R01) ; + end ">=" ; + + -- Id: C.23 +function ">=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return 0>R; end if; + return not UNSIGNED_LESS(L01, TO_UNSIGNED(R,L01'LENGTH)) ; + end ">=" ; + + -- Id: C.24 +function ">=" ( L: SIGNED; R: INTEGER) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +variable L01 : SIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(R)>L'length then return 0>R; end if; + return not SIGNED_LESS (L01, TO_SIGNED(R,L01'LENGTH)) ; + end ">=" ; + +--============================================================================= + + -- Id: C.25 +function "=" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return UNSIGNED_equal (RESIZE(L01,SIZE),RESIZE(R01,SIZE)) ; + end "=" ; + + -- Id: C.26 +function "=" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return SIGNED_equal (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end "=" ; + + -- Id: C.27 +function "=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(L)>R'Length then return FALSE; end if; + return UNSIGNED_equal ( TO_UNSIGNED(L,R01'LENGTH), R01); + end "=" ; + + -- Id: C.28 +function "=" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(L)>R'Length then return FALSE; end if; + return SIGNED_equal ( TO_SIGNED(L,R01'LENGTH), R01) ; + end "=" ; + + -- Id: C.29 +function "=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return FALSE; end if; + return UNSIGNED_equal (L01, TO_UNSIGNED (R,L01'LENGTH)) ; + end "=" ; + + -- Id: C.30 +function "=" ( L: SIGNED; R: INTEGER) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +variable L01 : SIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return FALSE; end if; + return SIGNED_equal (L01, TO_SIGNED (R,L01'LENGTH)) ; + end "=" ; + + +--============================================================================= + + -- Id: C.31 +function "/=" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL); + R01 := TO_01(XR); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return TRUE; end if; + return not(UNSIGNED_equal (RESIZE(L01,SIZE),RESIZE(R01,SIZE))) ; + end "/=" ; + + -- Id: C.32 +function "/=" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL); + R01 := TO_01(XR); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return TRUE; end if; + return not(SIGNED_equal (RESIZE(L01,SIZE), RESIZE(R01,SIZE))) ; + end "/=" ; + + -- Id: C.33 +function "/=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR); + if (R01(R01'left)='X') then return TRUE; end if; + if UNSIGNED_NUM_BITS(L)>R'Length then return TRUE; end if; + return not(UNSIGNED_equal ( TO_UNSIGNED(L,R01'LENGTH), R01)); + end "/=" ; + + -- Id: C.34 +function "/=" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR); + if (R01(R01'left)='X') then return TRUE; end if; + if Signed_NUM_BITS(L)>R'Length then return TRUE; end if; + return not(SIGNED_equal ( TO_SIGNED(L,R01'LENGTH), R01)) ; + end "/=" ; + + -- Id: C.35 +function "/=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL); + if (L01(L01'left)='X') then return TRUE; end if; + if UNSIGNED_NUM_BITS(R)>L'Length then return TRUE; end if; + return not(UNSIGNED_equal (L01, TO_UNSIGNED (R,L01'LENGTH))) ; + end "/=" ; + + -- Id: C.36 +function "/=" ( L: SIGNED; R: INTEGER) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +variable L01 : SIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL); + if (L01(L01'left)='X') then return TRUE; end if; + if Signed_NUM_BITS(R)>L'Length then return TRUE; end if; + return not(SIGNED_equal (L01, TO_SIGNED (R,L01'LENGTH))) ; + end "/=" ; + + +--============================================================================= + + -- Id: S.1 +function shift_left(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is +begin + if (ARG'length<1) then return NAU; end if; + return UNSIGNED(XSLL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.2 +function shift_right(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is +begin + if (ARG'length<1) then return NAU; end if; + return UNSIGNED(XSRL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.3 +function shift_left(ARG: SIGNED; COUNT: NATURAL) return SIGNED is +begin + if (ARG'length<1) then return NAS; end if; + return SIGNED(XSLL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.4 +function shift_right(ARG: SIGNED; COUNT: NATURAL) return SIGNED is +begin + if (ARG'length<1) then return NAS; end if; + return SIGNED(XSRA(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + +--============================================================================= + + -- Id: S.5 +function rotate_left(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is +begin + if (ARG'length<1) then return NAU; end if; + return UNSIGNED(XROL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.6 +function rotate_right(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is +begin + if (ARG'length<1) then return NAU; end if; + return UNSIGNED(XROR(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + + -- Id: S.7 +function rotate_left(ARG: SIGNED; COUNT: NATURAL) return SIGNED is +begin + if (ARG'length<1) then return NAS; end if; + return SIGNED(XROL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.8 +function rotate_right(ARG: SIGNED; COUNT: NATURAL) return SIGNED is +begin + if (ARG'length<1) then return NAS; end if; + return SIGNED(XROR(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + +--============================================================================= + + + -- Id: D.1 +function TO_INTEGER(ARG: UNSIGNED) return NATURAL is +constant ARG_LEFT:INTEGER:= ARG'length-1; +alias XXARG:UNSIGNED(ARG_LEFT downto 0) is ARG; +variable XARG:UNSIGNED(ARG_LEFT downto 0); +variable RESULT: NATURAL:= 0; +variable w : INTEGER:= 1; -- weight factor +begin + if (ARG'length<1) then + assert NO_WARNING + report "numeric_std.TO_INTEGER: null arg" + severity warning; + return 0; + end if; + XARG:= TO_01(XXARG); + if (XARG(XARG'left)='X') then + assert NO_WARNING + report "numeric_std.TO_INTEGER: metavalue arg set to 0" + severity warning; + return 0; + end if; + for i in XARG'reverse_range loop + if XARG (i) = '1' then + RESULT:= RESULT + w; + end if; + if (i /= XARG'left) then w := w + w; + end if; + end loop; + return RESULT; + end TO_INTEGER; + + -- Id: D.2 +function TO_INTEGER(ARG: SIGNED) return INTEGER is +begin + if ARG(ARG'left) = '0' then + return TO_INTEGER( UNSIGNED (ARG)) ; + else + return (- (TO_INTEGER( UNSIGNED ( - (ARG + 1)))) -1); + end if; + end TO_INTEGER; + + -- Id: D.3 +function TO_UNSIGNED(ARG,SIZE: NATURAL) return UNSIGNED is + variable RESULT: UNSIGNED (SIZE-1 downto 0) ; + variable i_val:natural := ARG; + begin + if (SIZE < 1) then return NAU; end if; + for i in 0 to RESULT'left loop + if (i_val MOD 2) = 0 then + RESULT(i) := '0'; + else RESULT(i) := '1' ; + end if; + i_val := i_val/2 ; + end loop; + if not(i_val=0) then + assert NO_WARNING + report "numeric_std.TO_UNSIGNED : vector truncated" + severity WARNING ; + end if; + return RESULT ; + end TO_UNSIGNED; + + -- Id: D.4 +function TO_SIGNED(ARG: INTEGER; SIZE: NATURAL) return SIGNED is + variable RESULT: SIGNED (SIZE-1 downto 0) ; + variable b_val : STD_LOGIC:= '0' ; + variable i_val : INTEGER:= ARG ; + begin + if (SIZE < 1) then return NAS; end if; + if (ARG<0) then + b_val := '1' ; + i_val := -(ARG+1) ; + end if ; + for i in 0 to RESULT'left loop + if (i_val MOD 2) = 0 then + RESULT(i) := b_val; + else + RESULT(i) := not b_val ; + end if; + i_val := i_val/2 ; + end loop; + if ((i_val/=0) or (b_val/=RESULT(RESULT'left))) then + assert NO_WARNING + report "numeric_std.TO_SIGNED : vector truncated" + severity WARNING ; + end if; + return RESULT; + end TO_SIGNED; + + -- Id: D.5 +function TO_UNSIGNED(ARG: STD_LOGIC_VECTOR) return UNSIGNED is + begin + return UNSIGNED(ARG); + end TO_UNSIGNED; + + -- Id: D.6 +function TO_SIGNED(ARG: STD_LOGIC_VECTOR) return SIGNED is + begin + return SIGNED(ARG); + end TO_SIGNED; + + -- Id: D.7 +function TO_STDLOGICVECTOR(ARG: UNSIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(ARG); + end TO_STDLOGICVECTOR; + + -- Id: D.8 +function TO_STDLOGICVECTOR(ARG: SIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(ARG); + end TO_STDLOGICVECTOR; + +--============================================================================= + + + -- Id: R.1 +function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED is +alias invec : SIGNED (ARG'length-1 downto 0) is ARG ; +variable RESULT: SIGNED (NEW_SIZE-1 downto 0) ; +constant bound : NATURAL:= MIN(ARG'length,RESULT'length)-2 ; +begin + if (NEW_SIZE<1) then return NAS; end if; + RESULT:= (others=>ARG(ARG'left)) ; + if bound >= 0 then + RESULT(bound downto 0) := invec(bound downto 0) ; + end if; + return RESULT; + end RESIZE ; + + + -- Id: R.2 +function RESIZE ( ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED is +constant ARG_LEFT:INTEGER:= ARG'length-1; +alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; +variable RESULT: UNSIGNED(NEW_SIZE-1 downto 0) := (others=>'0'); +begin + if (NEW_SIZE<1) then return NAU; end if; + if XARG'length=0 then return RESULT; + end if; + if (RESULT'length < ARG'length) then + RESULT(RESULT'left downto 0) := XARG(RESULT'left downto 0); + else + RESULT(RESULT'left downto XARG'left+1) := (others => '0'); + RESULT(XARG'left downto 0) := XARG; + end if; + return RESULT; + end RESIZE; + + + --============================================================================ + + -- Id: L.1 +function "not" ( L: UNSIGNED) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(not(STD_LOGIC_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.2 +function "and" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) and STD_LOGIC_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.3 +function "or" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) or STD_LOGIC_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.4 +function "nand" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) nand STD_LOGIC_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.5 +function "nor" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) nor STD_LOGIC_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.6 +function "xor" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) xor STD_LOGIC_VECTOR(R)); + return RESULT; + end "xor"; + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this 1076.3 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + -- Id: L.7 +--function "xnor" ( L,R: UNSIGNED ) return UNSIGNED is +--variable RESULT: UNSIGNED (L'range); +--begin +-- RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) xnor STD_LOGIC_VECTOR(R)); +-- return RESULT; +-- end "xnor"; + + -- Id: L.8 +function "not" ( L: SIGNED) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(not(STD_LOGIC_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.9 +function "and" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) and STD_LOGIC_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.10 +function "or" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) or STD_LOGIC_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.11 +function "nand" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) nand STD_LOGIC_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.12 +function "nor" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) nor STD_LOGIC_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.13 +function "xor" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) xor STD_LOGIC_VECTOR(R)); + return RESULT; + end "xor"; + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this 1076.3 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + -- Id: L.14 +--function "xnor" ( L,R: SIGNED ) return SIGNED is +--variable RESULT: SIGNED (L'range); +--begin +-- RESULT:= SIGNED(STD_LOGIC_VECTOR(L) xnor STD_LOGIC_VECTOR(R)); +-- return RESULT; +-- end "xnor"; + +--============================================================================= + +-- support constants for STD_MATCH: + + type STDULOGIC_TABLE is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; + + -- truth table for "and" function + constant AND_TABLE : STDULOGIC_TABLE := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -- | U | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 1 | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | Z | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | H | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ) -- | - | + ); + + -- truth table for STD_MATCH function + constant MATCH_TABLE : STDULOGIC_TABLE := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | X | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', '1' ), -- | 0 | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', '1' ), -- | 1 | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | Z | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | W | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', '1' ), -- | L | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', '1' ), -- | H | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ) -- | - | + ); + + -- Id: M.1 +function STD_MATCH (L, R: STD_ULOGIC) return BOOLEAN is + variable VALUE : STD_ULOGIC; + begin + VALUE := MATCH_TABLE(L, R); + return VALUE = '1'; + end STD_MATCH; + + + -- Id: M.2 +function STD_MATCH (L, R: STD_LOGIC_VECTOR) return BOOLEAN is + alias LV: STD_LOGIC_VECTOR ( 1 to L'LENGTH ) is L; + alias RV: STD_LOGIC_VECTOR ( 1 to R'LENGTH ) is R; + variable VALUE: STD_ULOGIC:= '1'; + begin + -- Check that both input vectors are the same length. + if LV'LENGTH /= RV'LENGTH then + assert NO_WARNING + report "STD_MATCH input arguments are not of equal length" + severity warning; + return FALSE; + else + for i in LV'LOW to LV'HIGH loop + VALUE := AND_TABLE(MATCH_TABLE(LV(i), RV(i)), VALUE); + end loop; + return VALUE = '1'; + end if; + end STD_MATCH; + + + +--============================================================================= +end numeric_std; + + + + diff --git a/lib/Standard/ieee/old/numeric_bit.vhd b/lib/Standard/ieee/old/numeric_bit.vhd new file mode 100644 index 0000000..2825cf9 --- /dev/null +++ b/lib/Standard/ieee/old/numeric_bit.vhd @@ -0,0 +1,2573 @@ +-- ----------------------------------------------------------------------------- +-- +-- Copyright 1995 by IEEE. All rights reserved. +-- +-- This source file is considered by the IEEE to be an essential part of the use +-- of the standard 1076.3 and as such may be distributed without change, except +-- as permitted by the standard. This source file may not be sold or distributed +-- for profit. This package may be modified to include additional data required +-- by tools, but must in no way change the external interfaces or simulation +-- behaviour of the description. It is permissible to add comments and/or +-- attributes to the package declarations, but not to change or delete any +-- original lines of the approved package declaration. The package body may be +-- changed only in accordance with the terms of clauses 7.1 and 7.2 of the +-- standard. +-- +-- Title : Standard VHDL Synthesis Package (1076.3, NUMERIC_BIT) +-- +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : -- > UNSIGNED: represents an UNSIGNED number in vector form +-- : -- > SIGNED: represents a SIGNED number in vector form +-- : The base element type is type BIT. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions, clock detection +-- : functions, and other utility functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- +-- Limitation : +-- +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : NUMERIC_BIT. The NUMERIC_BIT package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- ----------------------------------------------------------------------------- +-- Version : 2.4 +-- Date : 12 April 1995 +-- ----------------------------------------------------------------------------- + +package NUMERIC_BIT is + constant CopyRightNotice: STRING + := "Copyright 1995 IEEE. All rights reserved."; + + --============================================================================ + -- Numeric array type definitions + --============================================================================ + + type UNSIGNED is array (NATURAL range <> ) of BIT; + type SIGNED is array (NATURAL range <> ) of BIT; + + --============================================================================ + -- Arithmetic Operators: + --============================================================================ + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector ARG. + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --============================================================================ + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L(may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'LENGTH+L'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- size L'LENGTH before multiplication. + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'LENGTH+R'LENGTH-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- size R'LENGTH before multiplication. + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'LENGTH+L'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of size L'LENGTH before + -- multiplication. + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'LENGTH+R'LENGTH-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of size R'LENGTH before + -- multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, result is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, result is truncated to R'LENGTH. + + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits are lost. + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT rightmost bits are lost. + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits, except ARG'LEFT, are lost. + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost bit, ARG'LEFT. + -- The COUNT rightmost bits are lost. + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate-right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED vector COUNT times. + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED vector COUNT times. + + --============================================================================ + + ------------------------------------------------------------------------------ + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: SHIFT_RIGHT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)) + + ------------------------------------------------------------------------------ + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_LEFT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + ------------------------------------------------------------------------------ + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ROTATE_RIGHT(ARG, COUNT) + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the SIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(NEW_SIZE-1 downto 0) + -- Result: Resizes the UNSIGNED vector ARG to the specified size. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified size. + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified size. + + --============================================================================ + -- Logical Operators + --============================================================================ + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ------------------------------------------------------------------------------ + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Termwise inversion + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector AND operation + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XOR operation + + ------------------------------------------------------------------------------ + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Vector XNOR operation + + --============================================================================ + -- Edge Detection Functions + --============================================================================ + + -- Id: E.1 + function RISING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '0' to a '1'. + + -- Id: E.2 + function FALLING_EDGE (signal S: BIT) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Returns TRUE if an event is detected on signal S and the + -- value changed from a '1' to a '0'. + +end NUMERIC_BIT; + +--============================================================================== +--======================= Package Body ========================================= +--============================================================================== + +package body NUMERIC_BIT is + + -- null range array constants + + constant NAU: UNSIGNED(0 downto 1) := (others => '0'); + constant NAS: SIGNED(0 downto 1) := (others => '0'); + + -- implementation controls + + constant NO_WARNING: BOOLEAN := FALSE; -- default to emit warnings + + --=========================Local Subprograms ================================= + + function MAX (LEFT, RIGHT: INTEGER) return INTEGER is + begin + if LEFT > RIGHT then return LEFT; + else return RIGHT; + end if; + end MAX; + + function MIN (LEFT, RIGHT: INTEGER) return INTEGER is + begin + if LEFT < RIGHT then return LEFT; + else return RIGHT; + end if; + end MIN; + + function SIGNED_NUM_BITS (ARG: INTEGER) return NATURAL is + variable NBITS: NATURAL; + variable N: NATURAL; + begin + if ARG >= 0 then + N := ARG; + else + N := -(ARG+1); + end if; + NBITS := 1; + while N > 0 loop + NBITS := NBITS+1; + N := N / 2; + end loop; + return NBITS; + end SIGNED_NUM_BITS; + + function UNSIGNED_NUM_BITS (ARG: NATURAL) return NATURAL is + variable NBITS: NATURAL; + variable N: NATURAL; + begin + N := ARG; + NBITS := 1; + while N > 1 loop + NBITS := NBITS+1; + N := N / 2; + end loop; + return NBITS; + end UNSIGNED_NUM_BITS; + + ------------------------------------------------------------------------------ + -- this internal function computes the addition of two UNSIGNED + -- with input carry + -- * the two arguments are of the same length + + function ADD_UNSIGNED (L, R: UNSIGNED; C: BIT) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(L_LEFT downto 0) is R; + variable RESULT: UNSIGNED(L_LEFT downto 0); + variable CBIT: BIT := C; + begin + for I in 0 to L_LEFT loop + RESULT(I) := CBIT xor XL(I) xor XR(I); + CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); + end loop; + return RESULT; + end ADD_UNSIGNED; + + -- this internal function computes the addition of two SIGNED + -- with input carry + -- * the two arguments are of the same length + + function ADD_SIGNED (L, R: SIGNED; C: BIT) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + alias XL: SIGNED(L_LEFT downto 0) is L; + alias XR: SIGNED(L_LEFT downto 0) is R; + variable RESULT: SIGNED(L_LEFT downto 0); + variable CBIT: BIT := C; + begin + for I in 0 to L_LEFT loop + RESULT(I) := CBIT xor XL(I) xor XR(I); + CBIT := (CBIT and XL(I)) or (CBIT and XR(I)) or (XL(I) and XR(I)); + end loop; + return RESULT; + end ADD_SIGNED; + + ------------------------------------------------------------------------------ + + -- this internal procedure computes UNSIGNED division + -- giving the quotient and remainder. + procedure DIVMOD (NUM, XDENOM: UNSIGNED; XQUOT, XREMAIN: out UNSIGNED) is + variable TEMP: UNSIGNED(NUM'LENGTH downto 0); + variable QUOT: UNSIGNED(MAX(NUM'LENGTH, XDENOM'LENGTH)-1 downto 0); + alias DENOM: UNSIGNED(XDENOM'LENGTH-1 downto 0) is XDENOM; + variable TOPBIT: INTEGER; + begin + TEMP := "0"&NUM; + QUOT := (others => '0'); + TOPBIT := -1; + for J in DENOM'RANGE loop + if DENOM(J)='1' then + TOPBIT := J; + exit; + end if; + end loop; + assert TOPBIT >= 0 report "DIV, MOD, or REM by zero" severity ERROR; + + for J in NUM'LENGTH-(TOPBIT+1) downto 0 loop + if TEMP(TOPBIT+J+1 downto J) >= "0"&DENOM(TOPBIT downto 0) then + TEMP(TOPBIT+J+1 downto J) := (TEMP(TOPBIT+J+1 downto J)) + -("0"&DENOM(TOPBIT downto 0)); + QUOT(J) := '1'; + end if; + assert TEMP(TOPBIT+J+1)='0' + report "internal error in the division algorithm" + severity ERROR; + end loop; + XQUOT := RESIZE(QUOT, XQUOT'LENGTH); + XREMAIN := RESIZE(TEMP, XREMAIN'LENGTH); + end DIVMOD; + + -----------------Local Subprograms - shift/rotate ops------------------------- + + function XSLL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := (others => '0'); + begin + if COUNT <= ARG_L then + RESULT(ARG_L downto COUNT) := XARG(ARG_L-COUNT downto 0); + end if; + return RESULT; + end XSLL; + + function XSRL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := (others => '0'); + begin + if COUNT <= ARG_L then + RESULT(ARG_L-COUNT downto 0) := XARG(ARG_L downto COUNT); + end if; + return RESULT; + end XSRL; + + function XSRA (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0); + variable XCOUNT: NATURAL := COUNT; + begin + if ((ARG'LENGTH <= 1) or (XCOUNT = 0)) then return ARG; + else + if (XCOUNT > ARG_L) then XCOUNT := ARG_L; + end if; + RESULT(ARG_L-XCOUNT downto 0) := XARG(ARG_L downto XCOUNT); + RESULT(ARG_L downto (ARG_L - XCOUNT + 1)) := (others => XARG(ARG_L)); + end if; + return RESULT; + end XSRA; + + function XROL (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := XARG; + variable COUNTM: INTEGER; + begin + COUNTM := COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L downto COUNTM) := XARG(ARG_L-COUNTM downto 0); + RESULT(COUNTM-1 downto 0) := XARG(ARG_L downto ARG_L-COUNTM+1); + end if; + return RESULT; + end XROL; + + function XROR (ARG: BIT_VECTOR; COUNT: NATURAL) return BIT_VECTOR is + constant ARG_L: INTEGER := ARG'LENGTH-1; + alias XARG: BIT_VECTOR(ARG_L downto 0) is ARG; + variable RESULT: BIT_VECTOR(ARG_L downto 0) := XARG; + variable COUNTM: INTEGER; + begin + COUNTM := COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L-COUNTM downto 0) := XARG(ARG_L downto COUNTM); + RESULT(ARG_L downto ARG_L-COUNTM+1) := XARG(COUNTM-1 downto 0); + end if; + return RESULT; + end XROR; + + ---------------- Local Subprograms - Relational Operators -------------------- + + -- General "=" for UNSIGNED vectors, same length + -- + function UNSIGNED_EQUAL (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) = BIT_VECTOR(R); + end UNSIGNED_EQUAL; + + -- + -- General "=" for SIGNED vectors, same length + -- + function SIGNED_EQUAL (L, R: SIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) = BIT_VECTOR(R); + end SIGNED_EQUAL; + + -- + -- General "<" for UNSIGNED vectors, same length + -- + function UNSIGNED_LESS (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) < BIT_VECTOR(R); + end UNSIGNED_LESS; + + -- + -- General "<" function for SIGNED vectors, same length + -- + function SIGNED_LESS (L, R: SIGNED) return BOOLEAN is + -- Need aliases to assure index direction + variable INTERN_L: SIGNED(0 to L'LENGTH-1); + variable INTERN_R: SIGNED(0 to R'LENGTH-1); + begin + INTERN_L := L; + INTERN_R := R; + INTERN_L(0) := not INTERN_L(0); + INTERN_R(0) := not INTERN_R(0); + return BIT_VECTOR(INTERN_L) < BIT_VECTOR(INTERN_R); + end SIGNED_LESS; + + -- + -- General "<=" function for UNSIGNED vectors, same length + -- + function UNSIGNED_LESS_OR_EQUAL (L, R: UNSIGNED) return BOOLEAN is + begin + return BIT_VECTOR(L) <= BIT_VECTOR(R); + end UNSIGNED_LESS_OR_EQUAL; + + -- + -- General "<=" function for SIGNED vectors, same length + -- + function SIGNED_LESS_OR_EQUAL (L, R: SIGNED) return BOOLEAN is + -- Need aliases to assure index direction + variable INTERN_L: SIGNED(0 to L'LENGTH-1); + variable INTERN_R: SIGNED(0 to R'LENGTH-1); + begin + INTERN_L := L; + INTERN_R := R; + INTERN_L(0) := not INTERN_L(0); + INTERN_R(0) := not INTERN_R(0); + return BIT_VECTOR(INTERN_L) <= BIT_VECTOR(INTERN_R); + end SIGNED_LESS_OR_EQUAL; + + --====================== Exported Functions ================================== + + -- Id: A.1 + function "abs" (ARG: SIGNED) return SIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + variable RESULT: SIGNED(ARG_LEFT downto 0); + begin + if ARG'LENGTH < 1 then return NAS; + end if; + RESULT := ARG; + if RESULT(RESULT'LEFT) = '1' then + RESULT := -RESULT; + end if; + return RESULT; + end "abs"; + + -- Id: A.2 + function "-" (ARG: SIGNED) return SIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: SIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: SIGNED(ARG_LEFT downto 0); + variable CBIT: BIT := '1'; + begin + if ARG'LENGTH < 1 then return NAS; + end if; + for I in 0 to RESULT'LEFT loop + RESULT(I) := not(XARG(I)) xor CBIT; + CBIT := CBIT and not(XARG(I)); + end loop; + return RESULT; + end "-"; + + --============================================================================ + + -- Id: A.3 + function "+" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + return ADD_UNSIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); + end "+"; + + -- Id: A.4 + function "+" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + return ADD_SIGNED(RESIZE(L, SIZE), RESIZE(R, SIZE), '0'); + end "+"; + + -- Id: A.5 + function "+" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L + TO_UNSIGNED(R, L'LENGTH); + end "+"; + + -- Id: A.6 + function "+" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) + R; + end "+"; + + -- Id: A.7 + function "+" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L + TO_SIGNED(R, L'LENGTH); + end "+"; + + -- Id: A.8 + function "+" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) + R; + end "+"; + + --============================================================================ + + -- Id: A.9 + function "-" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + return ADD_UNSIGNED(RESIZE(L, SIZE), + not(RESIZE(R, SIZE)), + '1'); + end "-"; + + -- Id: A.10 + function "-" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + constant SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + return ADD_SIGNED(RESIZE(L, SIZE), + not(RESIZE(R, SIZE)), + '1'); + end "-"; + + -- Id: A.11 + function "-" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L - TO_UNSIGNED(R, L'LENGTH); + end "-"; + + -- Id: A.12 + function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) - R; + end "-"; + + -- Id: A.13 + function "-" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L - TO_SIGNED(R, L'LENGTH); + end "-"; + + -- Id: A.14 + function "-" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) - R; + end "-"; + + --============================================================================ + + -- Id: A.15 + function "*" (L, R: UNSIGNED) return UNSIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + alias XL: UNSIGNED(L_LEFT downto 0) is L; + alias XR: UNSIGNED(R_LEFT downto 0) is R; + variable RESULT: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0) := (others => '0'); + variable ADVAL: UNSIGNED((L'LENGTH+R'LENGTH-1) downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + ADVAL := RESIZE(XR, RESULT'LENGTH); + for I in 0 to L_LEFT loop + if XL(I)='1' then RESULT := RESULT + ADVAL; + end if; + ADVAL := SHIFT_LEFT(ADVAL, 1); + end loop; + return RESULT; + end "*"; + + -- Id: A.16 + function "*" (L, R: SIGNED) return SIGNED is + constant L_LEFT: INTEGER := L'LENGTH-1; + constant R_LEFT: INTEGER := R'LENGTH-1; + variable XL: SIGNED(L_LEFT downto 0); + variable XR: SIGNED(R_LEFT downto 0); + variable RESULT: SIGNED((L_LEFT+R_LEFT+1) downto 0) := (others => '0'); + variable ADVAL: SIGNED((L_LEFT+R_LEFT+1) downto 0); + begin + if ((L_LEFT < 0) or (R_LEFT < 0)) then return NAS; + end if; + XL := L; + XR := R; + ADVAL := RESIZE(XR, RESULT'LENGTH); + for I in 0 to L_LEFT-1 loop + if XL(I)='1' then RESULT := RESULT + ADVAL; + end if; + ADVAL := SHIFT_LEFT(ADVAL, 1); + end loop; + if XL(L_LEFT)='1' then + RESULT := RESULT - ADVAL; + end if; + return RESULT; + end "*"; + + -- Id: A.17 + function "*" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + begin + return L * TO_UNSIGNED(R, L'LENGTH); + end "*"; + + -- Id: A.18 + function "*" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + begin + return TO_UNSIGNED(L, R'LENGTH) * R; + end "*"; + + -- Id: A.19 + function "*" (L: SIGNED; R: INTEGER) return SIGNED is + begin + return L * TO_SIGNED(R, L'LENGTH); + end "*"; + + -- Id: A.20 + function "*" (L: INTEGER; R: SIGNED) return SIGNED is + begin + return TO_SIGNED(L, R'LENGTH) * R; + end "*"; + + --============================================================================ + + -- Id: A.21 + function "/" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FQUOT; + end "/"; + + -- Id: A.22 + function "/" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable QNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + QNEG := TRUE; + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + QNEG := not QNEG; + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if QNEG then FQUOT := "0"-FQUOT; + end if; + return SIGNED(FQUOT); + end "/"; + + -- Id: A.23 + function "/" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, QUOT: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + if (R_LENGTH > L'LENGTH) then + QUOT := (others => '0'); + return RESIZE(QUOT, L'LENGTH); + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + QUOT := RESIZE((L / XR), QUOT'LENGTH); + return RESIZE(QUOT, L'LENGTH); + end "/"; + + -- Id: A.24 + function "/" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, QUOT: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + QUOT := RESIZE((XL / R), QUOT'LENGTH); + if L_LENGTH > R'LENGTH + and QUOT(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""/"": Quotient Truncated" + severity WARNING; + end if; + return RESIZE(QUOT, R'LENGTH); + end "/"; + + -- Id: A.25 + function "/" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, QUOT: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + if (R_LENGTH > L'LENGTH) then + QUOT := (others => '0'); + return RESIZE(QUOT, L'LENGTH); + end if; + XR := TO_SIGNED(R, R_LENGTH); + QUOT := RESIZE((L / XR), QUOT'LENGTH); + return RESIZE(QUOT, L'LENGTH); + end "/"; + + -- Id: A.26 + function "/" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, QUOT: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + QUOT := RESIZE((XL / R), QUOT'LENGTH); + if L_LENGTH > R'LENGTH and QUOT(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => QUOT(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""/"": Quotient Truncated" + severity WARNING; + end if; + return RESIZE(QUOT, R'LENGTH); + end "/"; + + --============================================================================ + + -- Id: A.27 + function "rem" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FREMAIN; + end "rem"; + + -- Id: A.28 + function "rem" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable RNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + RNEG := TRUE; + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if RNEG then + FREMAIN := "0"-FREMAIN; + end if; + return SIGNED(FREMAIN); + end "rem"; + + -- Id: A.29 + function "rem" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, XREM: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + XREM := RESIZE((L rem XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "rem"; + + -- Id: A.30 + function "rem" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + XREM := RESIZE((XL rem R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "rem"; + + -- Id: A.31 + function "rem" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, XREM: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + XR := TO_SIGNED(R, R_LENGTH); + XREM := RESIZE((L rem XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => XREM(L'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "rem"; + + -- Id: A.32 + function "rem" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + XREM := RESIZE((XL rem R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => XREM(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""rem"": Remainder Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "rem"; + + --============================================================================ + + -- Id: A.33 + function "mod" (L, R: UNSIGNED) return UNSIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAU; + end if; + DIVMOD(L, R, FQUOT, FREMAIN); + return FREMAIN; + end "mod"; + + -- Id: A.34 + function "mod" (L, R: SIGNED) return SIGNED is + variable FQUOT: UNSIGNED(L'LENGTH-1 downto 0); + variable FREMAIN: UNSIGNED(R'LENGTH-1 downto 0); + variable XNUM: UNSIGNED(L'LENGTH-1 downto 0); + variable XDENOM: UNSIGNED(R'LENGTH-1 downto 0); + variable RNEG: BOOLEAN := FALSE; + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then return NAS; + end if; + if L(L'LEFT)='1' then + XNUM := UNSIGNED(-L); + else + XNUM := UNSIGNED(L); + end if; + if R(R'LEFT)='1' then + XDENOM := UNSIGNED(-R); + RNEG := TRUE; + else + XDENOM := UNSIGNED(R); + end if; + DIVMOD(XNUM, XDENOM, FQUOT, FREMAIN); + if RNEG and L(L'LEFT)='1' then + FREMAIN := "0"-FREMAIN; + elsif RNEG and FREMAIN/="0" then + FREMAIN := FREMAIN-XDENOM; + elsif L(L'LEFT)='1' and FREMAIN/="0" then + FREMAIN := XDENOM-FREMAIN; + end if; + return SIGNED(FREMAIN); + end "mod"; + + -- Id: A.35 + function "mod" (L: UNSIGNED; R: NATURAL) return UNSIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, UNSIGNED_NUM_BITS(R)); + variable XR, XREM: UNSIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAU; + end if; + XR := TO_UNSIGNED(R, R_LENGTH); + XREM := RESIZE((L mod XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "mod"; + + -- Id: A.36 + function "mod" (L: NATURAL; R: UNSIGNED) return UNSIGNED is + constant L_LENGTH: NATURAL := MAX(UNSIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: UNSIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAU; + end if; + XL := TO_UNSIGNED(L, L_LENGTH); + XREM := RESIZE((XL mod R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => '0') + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "mod"; + + -- Id: A.37 + function "mod" (L: SIGNED; R: INTEGER) return SIGNED is + constant R_LENGTH: NATURAL := MAX(L'LENGTH, SIGNED_NUM_BITS(R)); + variable XR, XREM: SIGNED(R_LENGTH-1 downto 0); + begin + if (L'LENGTH < 1) then return NAS; + end if; + XR := TO_SIGNED(R, R_LENGTH); + XREM := RESIZE((L mod XR), XREM'LENGTH); + if R_LENGTH > L'LENGTH and XREM(R_LENGTH-1 downto L'LENGTH) + /= (R_LENGTH-1 downto L'LENGTH => XREM(L'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, L'LENGTH); + end "mod"; + + -- Id: A.38 + function "mod" (L: INTEGER; R: SIGNED) return SIGNED is + constant L_LENGTH: NATURAL := MAX(SIGNED_NUM_BITS(L), R'LENGTH); + variable XL, XREM: SIGNED(L_LENGTH-1 downto 0); + begin + if (R'LENGTH < 1) then return NAS; + end if; + XL := TO_SIGNED(L, L_LENGTH); + XREM := RESIZE((XL mod R), XREM'LENGTH); + if L_LENGTH > R'LENGTH and XREM(L_LENGTH-1 downto R'LENGTH) + /= (L_LENGTH-1 downto R'LENGTH => XREM(R'LENGTH-1)) + then + assert NO_WARNING report "NUMERIC_BIT.""mod"": modulus Truncated" + severity WARNING; + end if; + return RESIZE(XREM, R'LENGTH); + end "mod"; + + --============================================================================ + + -- Id: C.1 + function ">" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">"; + + -- Id: C.2 + function ">" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not SIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">"; + + -- Id: C.3 + function ">" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end ">"; + + -- Id: C.4 + function ">" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not SIGNED_LESS_OR_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end ">"; + + -- Id: C.5 + function ">" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return not UNSIGNED_LESS_OR_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end ">"; + + -- Id: C.6 + function ">" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not SIGNED_LESS_OR_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end ">"; + + --============================================================================ + + -- Id: C.7 + function "<" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<"; + + -- Id: C.8 + function "<" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<"; + + -- Id: C.9 + function "<" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return UNSIGNED_LESS(TO_UNSIGNED(L, R'LENGTH), R); + end "<"; + + -- Id: C.10 + function "<" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return SIGNED_LESS(TO_SIGNED(L, R'LENGTH), R); + end "<"; + + -- Id: C.11 + function "<" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return UNSIGNED_LESS(L, TO_UNSIGNED(R, L'LENGTH)); + end "<"; + + -- Id: C.12 + function "<" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<"": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return SIGNED_LESS(L, TO_SIGNED(R, L'LENGTH)); + end "<"; + + --============================================================================ + + -- Id: C.13 + function "<=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<="; + + -- Id: C.14 + function "<=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_LESS_OR_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "<="; + + -- Id: C.15 + function "<=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return UNSIGNED_LESS_OR_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end "<="; + + -- Id: C.16 + function "<=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L < 0; + end if; + return SIGNED_LESS_OR_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end "<="; + + -- Id: C.17 + function "<=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return UNSIGNED_LESS_OR_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end "<="; + + -- Id: C.18 + function "<=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""<="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 < R; + end if; + return SIGNED_LESS_OR_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end "<="; + + --============================================================================ + + -- Id: C.19 + function ">=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not UNSIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">="; + + -- Id: C.20 + function ">=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return not SIGNED_LESS(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end ">="; + + -- Id: C.21 + function ">=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not UNSIGNED_LESS(TO_UNSIGNED(L, R'LENGTH), R); + end ">="; + + -- Id: C.22 + function ">=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return L > 0; + end if; + return not SIGNED_LESS(TO_SIGNED(L, R'LENGTH), R); + end ">="; + + -- Id: C.23 + function ">=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not UNSIGNED_LESS(L, TO_UNSIGNED(R, L'LENGTH)); + end ">="; + + -- Id: C.24 + function ">=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT."">="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return 0 > R; + end if; + return not SIGNED_LESS(L, TO_SIGNED(R, L'LENGTH)); + end ">="; + + --============================================================================ + + -- Id: C.25 + function "=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return UNSIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "="; + + -- Id: C.26 + function "=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + return SIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE)); + end "="; + + -- Id: C.27 + function "=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return FALSE; + end if; + return UNSIGNED_EQUAL(TO_UNSIGNED(L, R'LENGTH), R); + end "="; + + -- Id: C.28 + function "=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return FALSE; + end if; + return SIGNED_EQUAL(TO_SIGNED(L, R'LENGTH), R); + end "="; + + -- Id: C.29 + function "=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return UNSIGNED_EQUAL(L, TO_UNSIGNED(R, L'LENGTH)); + end "="; + + -- Id: C.30 + function "=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""="": null argument detected, returning FALSE" + severity WARNING; + return FALSE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return FALSE; + end if; + return SIGNED_EQUAL(L, TO_SIGNED(R, L'LENGTH)); + end "="; + + --============================================================================ + + -- Id: C.31 + function "/=" (L, R: UNSIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + return not(UNSIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE))); + end "/="; + + -- Id: C.32 + function "/=" (L, R: SIGNED) return BOOLEAN is + variable SIZE: NATURAL := MAX(L'LENGTH, R'LENGTH); + begin + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + return not(SIGNED_EQUAL(RESIZE(L, SIZE), RESIZE(R, SIZE))); + end "/="; + + -- Id: C.33 + function "/=" (L: NATURAL; R: UNSIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if UNSIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not(UNSIGNED_EQUAL(TO_UNSIGNED(L, R'LENGTH), R)); + end "/="; + + -- Id: C.34 + function "/=" (L: INTEGER; R: SIGNED) return BOOLEAN is + begin + if (R'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if SIGNED_NUM_BITS(L) > R'LENGTH then return TRUE; + end if; + return not(SIGNED_EQUAL(TO_SIGNED(L, R'LENGTH), R)); + end "/="; + + -- Id: C.35 + function "/=" (L: UNSIGNED; R: NATURAL) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if UNSIGNED_NUM_BITS(R) > L'LENGTH then return TRUE; + end if; + return not(UNSIGNED_EQUAL(L, TO_UNSIGNED(R, L'LENGTH))); + end "/="; + + -- Id: C.36 + function "/=" (L: SIGNED; R: INTEGER) return BOOLEAN is + begin + if (L'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.""/="": null argument detected, returning TRUE" + severity WARNING; + return TRUE; + end if; + if SIGNED_NUM_BITS(R) > L'LENGTH then return TRUE; + end if; + return not(SIGNED_EQUAL(L, TO_SIGNED(R, L'LENGTH))); + end "/="; + + --============================================================================ + + -- Id: S.1 + function SHIFT_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XSLL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_LEFT; + + -- Id: S.2 + function SHIFT_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XSRL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_RIGHT; + + -- Id: S.3 + function SHIFT_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XSLL(BIT_VECTOR(ARG), COUNT)); + end SHIFT_LEFT; + + -- Id: S.4 + function SHIFT_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XSRA(BIT_VECTOR(ARG), COUNT)); + end SHIFT_RIGHT; + + --============================================================================ + + -- Id: S.5 + function ROTATE_LEFT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XROL(BIT_VECTOR(ARG), COUNT)); + end ROTATE_LEFT; + + -- Id: S.6 + function ROTATE_RIGHT (ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is + begin + if (ARG'LENGTH < 1) then return NAU; + end if; + return UNSIGNED(XROR(BIT_VECTOR(ARG), COUNT)); + end ROTATE_RIGHT; + + -- Id: S.7 + function ROTATE_LEFT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XROL(BIT_VECTOR(ARG), COUNT)); + end ROTATE_LEFT; + + -- Id: S.8 + function ROTATE_RIGHT (ARG: SIGNED; COUNT: NATURAL) return SIGNED is + begin + if (ARG'LENGTH < 1) then return NAS; + end if; + return SIGNED(XROR(BIT_VECTOR(ARG), COUNT)); + end ROTATE_RIGHT; + + --============================================================================ + + ------------------------------------------------------------------------------ + -- Note : Function S.9 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.9 + function "sll" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SHIFT_RIGHT(ARG, -COUNT); + end if; + end "sll"; + + ------------------------------------------------------------------------------ + -- Note : Function S.10 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.10 + function "sll" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_LEFT(ARG, COUNT); + else + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), -COUNT)); + end if; + end "sll"; + + ------------------------------------------------------------------------------ + -- Note : Function S.11 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.11 + function "srl" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(ARG, COUNT); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end "srl"; + + ------------------------------------------------------------------------------ + -- Note : Function S.12 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.12 + function "srl" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return SIGNED(SHIFT_RIGHT(UNSIGNED(ARG), COUNT)); + else + return SHIFT_LEFT(ARG, -COUNT); + end if; + end "srl"; + + ------------------------------------------------------------------------------ + -- Note : Function S.13 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.13 + function "rol" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end "rol"; + + ------------------------------------------------------------------------------ + -- Note : Function S.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.14 + function "rol" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_LEFT(ARG, COUNT); + else + return ROTATE_RIGHT(ARG, -COUNT); + end if; + end "rol"; + + ------------------------------------------------------------------------------ + -- Note : Function S.15 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.15 + function "ror" (ARG: UNSIGNED; COUNT: INTEGER) return UNSIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end "ror"; + + ------------------------------------------------------------------------------ + -- Note : Function S.16 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: S.16 + function "ror" (ARG: SIGNED; COUNT: INTEGER) return SIGNED is + begin + if (COUNT >= 0) then + return ROTATE_RIGHT(ARG, COUNT); + else + return ROTATE_LEFT(ARG, -COUNT); + end if; + end "ror"; + + --============================================================================ + + -- Id: D.1 + function TO_INTEGER (ARG: UNSIGNED) return NATURAL is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: NATURAL := 0; + begin + if (ARG'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.TO_INTEGER: null detected, returning 0" + severity WARNING; + return 0; + end if; + for I in XARG'RANGE loop + RESULT := RESULT+RESULT; + if XARG(I) = '1' then + RESULT := RESULT + 1; + end if; + end loop; + return RESULT; + end TO_INTEGER; + + -- Id: D.2 + function TO_INTEGER (ARG: SIGNED) return INTEGER is + begin + if (ARG'LENGTH < 1) then + assert NO_WARNING + report "NUMERIC_BIT.TO_INTEGER: null detected, returning 0" + severity WARNING; + return 0; + end if; + if ARG(ARG'LEFT) = '0' then + return TO_INTEGER(UNSIGNED(ARG)); + else + return (- (TO_INTEGER(UNSIGNED(- (ARG + 1)))) -1); + end if; + end TO_INTEGER; + + -- Id: D.3 + function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED is + variable RESULT: UNSIGNED(SIZE-1 downto 0); + variable I_VAL: NATURAL := ARG; + begin + if (SIZE < 1) then return NAU; + end if; + for I in 0 to RESULT'LEFT loop + if (I_VAL mod 2) = 0 then + RESULT(I) := '0'; + else RESULT(I) := '1'; + end if; + I_VAL := I_VAL/2; + end loop; + if not(I_VAL =0) then + assert NO_WARNING + report "NUMERIC_BIT.TO_UNSIGNED: vector truncated" + severity WARNING; + end if; + return RESULT; + end TO_UNSIGNED; + + -- Id: D.4 + function TO_SIGNED (ARG: INTEGER; + SIZE: NATURAL) return SIGNED is + variable RESULT: SIGNED(SIZE-1 downto 0); + variable B_VAL: BIT := '0'; + variable I_VAL: INTEGER := ARG; + begin + if (SIZE < 1) then return NAS; + end if; + if (ARG < 0) then + B_VAL := '1'; + I_VAL := -(ARG+1); + end if; + for I in 0 to RESULT'LEFT loop + if (I_VAL mod 2) = 0 then + RESULT(I) := B_VAL; + else + RESULT(I) := not B_VAL; + end if; + I_VAL := I_VAL/2; + end loop; + if ((I_VAL/=0) or (B_VAL/=RESULT(RESULT'LEFT))) then + assert NO_WARNING + report "NUMERIC_BIT.TO_SIGNED: vector truncated" + severity WARNING; + end if; + return RESULT; + end TO_SIGNED; + + --============================================================================ + + -- Id: R.1 + function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED is + alias INVEC: SIGNED(ARG'LENGTH-1 downto 0) is ARG; + variable RESULT: SIGNED(NEW_SIZE-1 downto 0) := (others => '0'); + constant BOUND: INTEGER := MIN(ARG'LENGTH, RESULT'LENGTH)-2; + begin + if (NEW_SIZE < 1) then return NAS; + end if; + if (ARG'LENGTH = 0) then return RESULT; + end if; + RESULT := (others => ARG(ARG'LEFT)); + if BOUND >= 0 then + RESULT(BOUND downto 0) := INVEC(BOUND downto 0); + end if; + return RESULT; + end RESIZE; + + -- Id: R.2 + function RESIZE (ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED is + constant ARG_LEFT: INTEGER := ARG'LENGTH-1; + alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; + variable RESULT: UNSIGNED(NEW_SIZE-1 downto 0) := (others => '0'); + begin + if (NEW_SIZE < 1) then return NAU; + end if; + if XARG'LENGTH =0 then return RESULT; + end if; + if (RESULT'LENGTH < ARG'LENGTH) then + RESULT(RESULT'LEFT downto 0) := XARG(RESULT'LEFT downto 0); + else + RESULT(RESULT'LEFT downto XARG'LEFT+1) := (others => '0'); + RESULT(XARG'LEFT downto 0) := XARG; + end if; + return RESULT; + end RESIZE; + + --============================================================================ + + -- Id: L.1 + function "not" (L: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(not(BIT_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.2 + function "and" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) and BIT_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.3 + function "or" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) or BIT_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.4 + function "nand" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) nand BIT_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.5 + function "nor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) nor BIT_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.6 + function "xor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) xor BIT_VECTOR(R)); + return RESULT; + end "xor"; + + ------------------------------------------------------------------------------ + -- Note : Function L.7 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.7 + function "xnor" (L, R: UNSIGNED) return UNSIGNED is + variable RESULT: UNSIGNED(L'LENGTH-1 downto 0); + begin + RESULT := UNSIGNED(BIT_VECTOR(L) xnor BIT_VECTOR(R)); + return RESULT; + end "xnor"; + + -- Id: L.8 + function "not" (L: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(not(BIT_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.9 + function "and" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) and BIT_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.10 + function "or" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) or BIT_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.11 + function "nand" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) nand BIT_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.12 + function "nor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) nor BIT_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.13 + function "xor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) xor BIT_VECTOR(R)); + return RESULT; + end "xor"; + + ------------------------------------------------------------------------------ + -- Note : Function L.14 is not compatible with VHDL 1076-1987. Comment + -- out the function (declaration and body) for VHDL 1076-1987 compatibility. + ------------------------------------------------------------------------------ + -- Id: L.14 + function "xnor" (L, R: SIGNED) return SIGNED is + variable RESULT: SIGNED(L'LENGTH-1 downto 0); + begin + RESULT := SIGNED(BIT_VECTOR(L) xnor BIT_VECTOR(R)); + return RESULT; + end "xnor"; + + --============================================================================ + + -- Id: E.1 + function RISING_EDGE (signal S: BIT) return BOOLEAN is + begin + return S'EVENT and S = '1'; + end RISING_EDGE; + + -- Id: E.2 + function FALLING_EDGE (signal S: BIT) return BOOLEAN is + begin + return S'EVENT and S = '0'; + end FALLING_EDGE; + + --============================================================================ +end NUMERIC_BIT; diff --git a/lib/Standard/ieee/old/numeric_std.vhd b/lib/Standard/ieee/old/numeric_std.vhd new file mode 100644 index 0000000..65dde0a --- /dev/null +++ b/lib/Standard/ieee/old/numeric_std.vhd @@ -0,0 +1,2671 @@ +-- ---------------------------------------------------------------------------- +-- Title : NUMERIC_STD arithmetic package for synthesis +-- : Rev. 1.7 (Nov. 23 1994) +-- : +-- Library : This package shall be compiled into a library symbolically +-- : named IEEE. +-- : +-- Developers : IEEE DASC Synthesis Working Group, PAR 1076.3 +-- : +-- Purpose : This package defines numeric types and arithmetic functions +-- : for use with synthesis tools. Two numeric types are defined: +-- : --> UNSIGNED : represents UNSIGNED number in vector form +-- : --> SIGNED : represents a SIGNED number in vector form +-- : The base element type is type STD_LOGIC. +-- : The leftmost bit is treated as the most significant bit. +-- : Signed vectors are represented in two's complement form. +-- : This package contains overloaded arithmetic operators on +-- : the SIGNED and UNSIGNED types. The package also contains +-- : useful type conversions functions. +-- : +-- : If any argument to a function is a null array, a null array is +-- : returned (exceptions, if any, are noted individually). +-- : +-- Note : No declarations or definitions shall be included in, or +-- : excluded from, this package. The package declaration declares +-- : the functions that can be used by a user. The package body +-- : shall be considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement the +-- : package body in the most efficient manner available to them. +-- : +-- ---------------------------------------------------------------------------- +library ieee; +use ieee.STD_LOGIC_1164.all; + +Package numeric_std is + + --=========================================================================== + -- Numeric array type definitions + --=========================================================================== + + type UNSIGNED is array ( NATURAL range <> ) of STD_LOGIC; + type SIGNED is array ( NATURAL range <> ) of STD_LOGIC; + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + + -- Id: A.1 + function "abs" ( X : SIGNED) return SIGNED; + -- Result subtype: SIGNED(X'LENGTH-1 downto 0). + -- Result: Returns the absolute value of a SIGNED vector X. + + -- Id: A.2 + function "-" ( ARG: SIGNED) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0). + -- Result: Returns the value of the unary minus operation on a + -- SIGNED vector ARG. + + --============================================================================ + + -- Id: A.3 + function "+" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two UNSIGNED vectors that may be of different lengths. + + -- Id: A.4 + function "+" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Adds two SIGNED vectors that may be of different lengths. + + -- Id: A.5 + function "+" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0). + -- Result: Adds an UNSIGNED vector, L, with a non-negative INTEGER, R. + + -- Id: A.6 + function "+" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Adds a non-negative INTEGER, L, with an UNSIGNED vector, R. + + -- Id: A.7 + function "+" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED (R'LENGTH-1 downto 0). + -- Result: Adds an INTEGER, L (may be positive or negative), to a SIGNED + -- vector, R. + + -- Id: A.8 + function "+" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED (L'LENGTH-1 downto 0). + -- Result: Adds a SIGNED vector, L, to an INTEGER, R. + + --============================================================================ + + -- Id: A.9 + function "-" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts two UNSIGNED vectors that may be of different lengths. + + -- Id: A.10 + function "-" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(MAX(L'LENGTH, R'LENGTH)-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from another SIGNED vector, L, + -- that may possibly be of different lengths. + + -- Id: A.11 + function "-" ( L: UNSIGNED;R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (L'LENGTH-1 downto 0). + -- Result: Subtracts a non-negative INTEGER, R, from an UNSIGNED vector, L. + + -- Id: A.12 + function "-" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L. + + -- Id: A.13 + function "-" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED (L'LENGTH-1 downto 0). + -- Result: Subtracts an INTEGER, R, from a SIGNED vector, L. + + -- Id: A.14 + function "-" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0). + -- Result: Subtracts a SIGNED vector, R, from an INTEGER, L. + + --============================================================================ + + -- Id: A.15 + function "*" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED((L'length+R'length-1) downto 0). + -- Result: Performs the multiplication operation on two UNSIGNED vectors + -- that may possibly be of different lengths. + + -- Id: A.16 + function "*" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((L'length+R'length-1) downto 0) + -- Result: Multiplies two SIGNED vectors that may possibly be of + -- different lengths. + + -- Id: A.17 + function "*" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED((L'length+L'length-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, L, with a non-negative + -- INTEGER, R. R is converted to an UNSIGNED vector of + -- SIZE L'length before multiplication. + + -- Id: A.18 + function "*" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED((R'length+R'length-1) downto 0). + -- Result: Multiplies an UNSIGNED vector, R, with a non-negative + -- INTEGER, L. L is converted to an UNSIGNED vector of + -- SIZE R'length before multiplication. + + -- Id: A.19 + function "*" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED((L'length+L'length-1) downto 0) + -- Result: Multiplies a SIGNED vector, L, with an INTEGER, R. R is + -- converted to a SIGNED vector of SIZE L'length before + -- multiplication. + + -- Id: A.20 + function "*" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED((R'length+R'length-1) downto 0) + -- Result: Multiplies a SIGNED vector, R, with an INTEGER, L. L is + -- converted to a SIGNED vector of SIZE R'length before + -- multiplication. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "/" operator, a severity level + -- of ERROR is issued. + + -- Id: A.21 + function "/" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED (L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by another UNSIGNED vector, R. + + -- Id: A.22 + function "/" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED (L'LENGTH-1 downto 0) + -- Result: Divides an SIGNED vector, L, by another SIGNED vector, R. + + -- Id: A.23 + function "/" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (L'LENGTH-1 downto 0) + -- Result: Divides an UNSIGNED vector, L, by a non-negative INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.24 + function "/" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED (R'LENGTH-1 downto 0) + -- Result: Divides a non-negative INTEGER, L, by an UNSIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + -- Id: A.25 + function "/" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED (L'LENGTH-1 downto 0) + -- Result: Divides a SIGNED vector, L, by an INTEGER, R. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.26 + function "/" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED (R'LENGTH-1 downto 0) + -- Result: Divides an INTEGER, L, by a SIGNED vector, R. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "rem" operator, a severity level + -- of ERROR is issued. + + -- Id: A.27 + function "rem" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are UNSIGNED vectors. + + -- Id: A.28 + function "rem" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L and R are SIGNED vectors. + + -- Id: A.29 + function "rem" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is an UNSIGNED vector and R is a + -- non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.30 + function "rem" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is an UNSIGNED vector and L is a + -- non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + -- Id: A.31 + function "rem" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where L is SIGNED vector and R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.32 + function "rem" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L rem R" where R is SIGNED vector and L is an INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + --============================================================================ + -- + -- NOTE: If second argument is zero for "mod" operator, a severity level + -- of ERROR is issued. + + -- Id: A.33 + function "mod" (L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are UNSIGNED vectors. + + -- Id: A.34 + function "mod" ( L,R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L and R are SIGNED vectors. + + -- Id: A.35 + function "mod" ( L: UNSIGNED; R: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an UNSIGNED vector and R + -- is a non-negative INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.36 + function "mod" ( L: NATURAL; R: UNSIGNED) return UNSIGNED; + -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where R is an UNSIGNED vector and L + -- is a non-negative INTEGER. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + -- Id: A.37 + function "mod" ( L: SIGNED; R: INTEGER) return SIGNED; + -- Result subtype: SIGNED(L'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is a SIGNED vector and + -- R is an INTEGER. + -- If NO_OF_BITS(R) > L'LENGTH, then R is truncated to L'LENGTH. + + -- Id: A.38 + function "mod" ( L: INTEGER; R: SIGNED) return SIGNED; + -- Result subtype: SIGNED(R'LENGTH-1 downto 0) + -- Result: Computes "L mod R" where L is an INTEGER and + -- R is a SIGNED vector. + -- If NO_OF_BITS(L) > R'LENGTH, then L is truncated to R'LENGTH. + + --============================================================================ + -- Comparison Operators + --============================================================================ + + -- Id: C.1 + function ">" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.2 + function ">" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.3 + function ">" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.4 + function ">" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a INTEGER and + -- R is a SIGNED vector. + + -- Id: C.5 + function ">" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.6 + function ">" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L > R" where L is a SIGNED vector and + -- R is a INTEGER. + + --============================================================================ + + -- Id: C.7 + function "<" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.8 + function "<" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.9 + function "<" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.10 + function "<" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.11 + function "<" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.12 + function "<" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L < R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.13 + function "<=" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.14 + function "<=" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.15 + function "<=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.16 + function "<=" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.17 + function "<=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.18 + function "<=" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L <= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.19 + function ">=" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.20 + function ">=" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.21 + function ">=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.22 + function ">=" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.23 + function ">=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.24 + function ">=" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L >= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.25 + function "=" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.26 + function "=" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.27 + function "=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.28 + function "=" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.29 + function "=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.30 + function "=" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L = R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + + -- Id: C.31 + function "/=" (L,R: UNSIGNED ) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are UNSIGNED vectors possibly + -- of different lengths. + + -- Id: C.32 + function "/=" ( L,R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L and R are SIGNED vectors possibly + -- of different lengths. + + -- Id: C.33 + function "/=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a non-negative INTEGER and + -- R is an UNSIGNED vector. + + -- Id: C.34 + function "/=" ( L: INTEGER; R: SIGNED) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an INTEGER and + -- R is a SIGNED vector. + + -- Id: C.35 + function "/=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is an UNSIGNED vector and + -- R is a non-negative INTEGER. + + -- Id: C.36 + function "/=" ( L: SIGNED; R: INTEGER) return BOOLEAN; + -- Result subtype: BOOLEAN + -- Result: Computes "L /= R" where L is a SIGNED vector and + -- R is an INTEGER. + + --============================================================================ + -- Shift and Rotate Functions + --============================================================================ + + -- Id: S.1 + function shift_left ( ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits are lost. + + -- Id: S.2 + function shift_right ( ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on an UNSIGNED vector COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT rightmost bits are lost. + + -- Id: S.3 + function shift_left ( ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-left on a SIGNED vector COUNT times. + -- All bits of ARG, except ARG'LEFT, are shifted left COUNT times. + -- The vacated positions are filled with Bit '0'. + -- The COUNT leftmost bits, except ARG'LEFT, are lost. + + -- Id: S.4 + function shift_right ( ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a shift-right on a SIGNED vector COUNT times. + -- The vacated positions are filled with the leftmost bit,ARG'LEFT. + -- The COUNT rightmost bits are lost. + + --============================================================================ + + --============================================================================ + + -- Id: S.5 + function rotate_left ( ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate_left of an UNSIGNED vector COUNT times. + + -- Id: S.6 + function rotate_right ( ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a rotate_right of an UNSIGNED vector COUNT times. + + -- Id: S.7 + function rotate_left ( ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-left of a SIGNED + -- vector COUNT times. + + -- Id: S.8 + function rotate_right ( ARG: SIGNED; COUNT: NATURAL) return SIGNED; + -- Result subtype: SIGNED (ARG'LENGTH-1 downto 0) + -- Result: Performs a logical rotate-right of a SIGNED + -- vector COUNT times. + + --============================================================================ + -- RESIZE Functions + --============================================================================ + + -- Id: R.1 + function RESIZE ( ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED(ARG'LENGTH-1 downto 0) + -- Result: ReSIZEs the SIGNED vector ARG to the specified SIZE. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with the sign bit (ARG'LEFT). When truncating, + -- the sign bit is retained along with the rightmost part. + + -- Id: R.2 + function RESIZE ( ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED(ARG'LENGTH-1 downto 0) + -- Result: ReSIZEs the SIGNED vector ARG to the specified SIZE. + -- To create a larger vector, the new [leftmost] bit positions + -- are filled with '0'. When truncating, the leftmost bits + -- are dropped. + + + --============================================================================ + -- Conversion Functions + --============================================================================ + + -- Id: D.1 + function TO_INTEGER ( ARG: UNSIGNED) return NATURAL; + -- Result subtype: NATURAL. Value cannot be negative since parameter is an + -- UNSIGNED vector. + -- Result: Converts the UNSIGNED vector to an INTEGER. + + -- Id: D.2 + function TO_INTEGER ( ARG: SIGNED) return INTEGER; + -- Result subtype: INTEGER + -- Result: Converts a SIGNED vector to an INTEGER. + + -- Id: D.3 + function TO_UNSIGNED ( ARG,SIZE: NATURAL) return UNSIGNED; + -- Result subtype: UNSIGNED (SIZE-1 downto 0) + -- Result: Converts a non-negative INTEGER to an UNSIGNED vector with + -- the specified SIZE. + + -- Id: D.4 + function TO_SIGNED ( ARG: INTEGER; SIZE: NATURAL) return SIGNED; + -- Result subtype: SIGNED (SIZE-1 downto 0) + -- Result: Converts an INTEGER to a SIGNED vector of the specified SIZE. + + -- Id: D.5 + function TO_UNSIGNED ( ARG: STD_LOGIC_VECTOR) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input ARG + -- Result: Converts STD_LOGIC_VECTOR to UNSIGNED. + + -- Id: D.6 + function TO_SIGNED ( ARG: STD_LOGIC_VECTOR) return SIGNED; + -- Result subtype: SIGNED, same range as input ARG + -- Result: Converts STD_LOGIC_VECTOR to SIGNED. + + -- Id: D.7 + function TO_STDLOGICVECTOR ( ARG: UNSIGNED) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR, same range as input ARG + -- Result: Converts UNSIGNED to STD_LOGIC_VECTOR. + + -- Id: D.8 + function TO_STDLOGICVECTOR ( ARG: SIGNED) return STD_LOGIC_VECTOR; + -- Result subtype: STD_LOGIC_VECTOR, same range as input ARG + -- Result: Converts SIGNED to STD_LOGIC_VECTOR. + + --============================================================================ + -- Logical Operators + --============================================================================ + + -- Id: L.1 + function "not" ( L: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Termwise inversion + + -- Id: L.2 + function "and" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector AND operation + + -- Id: L.3 + function "or" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector OR operation + + -- Id: L.4 + function "nand" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector NAND operation + + -- Id: L.5 + function "nor" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector NOR operation + + -- Id: L.6 + function "xor" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector XOR operation + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this 1076.3 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + -- Id: L.7 +-- function "xnor" ( L,R: UNSIGNED ) return UNSIGNED; + -- Result subtype: UNSIGNED, same range as input L + -- Result: Vector XNOR operation + + -- Id: L.8 + function "not" ( L: SIGNED) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Termwise inversion + + -- Id: L.9 + function "and" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector AND operation + + -- Id: L.10 + function "or" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector OR operation + + -- Id: L.11 + function "nand" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector NAND operation + + -- Id: L.12 + function "nor" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector NOR operation + + -- Id: L.13 + function "xor" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector XOR operation + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this 1076.3 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + -- Id: L.14 +-- function "xnor" ( L,R: SIGNED ) return SIGNED; + -- Result subtype: SIGNED, same range as input L + -- Result: Vector XNOR operation + + --============================================================================ + -- Match Functions + --============================================================================ + + -- Id: M.1 + function STD_MATCH (L, R: STD_ULOGIC) return BOOLEAN; + -- Result: terms compared per STD_LOGIC_1164 intent + + -- Id: M.2 + function STD_MATCH (L, R: STD_LOGIC_VECTOR) return BOOLEAN; + -- Result: termwise comparison per STD_LOGIC_1164 intent + + end numeric_std; + +--============================================================================= +--======================= Package Body =============================== +--============================================================================= + + +Package body numeric_std is + + + -- null range array constants + +constant NAU : UNSIGNED (0 downto 1) := (others => '0'); +constant NAS : SIGNED (0 downto 1) := (others => '0'); + + -- implementation controls + +constant NO_WARNING : boolean := FALSE; -- default to emit warnings + +--=========================Local Subprograms================================= + +function MAX(LEFT, RIGHT: INTEGER) return INTEGER is +begin + if LEFT > RIGHT then return LEFT; + else return RIGHT; + end if; + end; + +function MIN(LEFT, RIGHT: INTEGER) return INTEGER is +begin + if LEFT < RIGHT then return LEFT; + else return RIGHT; + end if; + end; + +function Signed_NUM_BITS ( ARG: INTEGER) return natural is +variable nBits: natural; +variable N: natural; +begin + if ARG>=0 then + N:=ARG; + else + N:=-(ARG+1); + end if; + nBits:=1; + while N>0 loop + nBits:=nBits+1; + N:= N / 2; + end loop; + return nBits; + end; + +function UNSIGNED_NUM_BITS (ARG: natural) return natural is +variable nBits: natural; +variable N: natural; +begin + N:=ARG; + nBits:=1; + while N>1 loop + nBits:=nBits+1; + N:= N / 2; + end loop; + return nBits; + end; + + +------------------------------------------------------------------------ + + -- this internal function computes the addition of two UNSIGNED + -- with input CARRY + -- * the two arguments are of the same length + +function ADD_UNSIGNED ( L,R: UNSIGNED; C: STD_LOGIC ) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(L_left downto 0) is R; +variable RESULT: UNSIGNED(L_left downto 0); +variable CBIT : STD_LOGIC:= C; +begin + for i in 0 to L_left loop + RESULT(i) := CBIT xor XL(i) xor XR(i); + CBIT := (CBIT and XL(i)) or (CBIT and XR(i)) or (XL(i) and XR(i)); + end loop; + return RESULT; + end ADD_UNSIGNED; + + -- this internal function computes the addition of two SIGNED + -- with input CARRY + -- * the two arguments are of the same length + +function ADD_SIGNED ( L,R: SIGNED; C: STD_LOGIC ) return SIGNED is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(L_left downto 0) is R; +variable RESULT: SIGNED(L_left downto 0); +variable CBIT: STD_LOGIC:= C; +begin + for i in 0 to L_left loop + RESULT(i) := CBIT xor XL(i) xor XR(i); + CBIT := (CBIT and XL(i)) or (CBIT and XR(i)) or (XL(i) and XR(i)); + end loop; + return RESULT; + end ADD_SIGNED; + +------------------------------------------------------------------------ + + -- this internal procedure computes UNSIGNED division + -- giving the quotient and remainder. + procedure divMod (num, XDENOM: UNSIGNED; + xquot, xremain: out UNSIGNED) is + variable TEMP: UNSIGNED(num'length-1 downto 0); + variable quot: UNSIGNED(MAX(num'length,XDENOM'length)-1 downto 0); + variable diff: UNSIGNED(XDENOM'length downto 0); + alias DENOM : UNSIGNED (XDENOM'length-1 downto 0) is XDENOM; + variable CARRY: STD_LOGIC; + variable TOPBIT: natural; + variable isZero: boolean; + begin + isZero:=TRUE; + for j in XDENOM'range loop + CARRY:=DENOM(j); + if CARRY/='0' then + isZero:=FALSE; + end if; + end loop; + assert not isZero + report "DIV,MOD,or REM by zero" + severity error; + TEMP:=num; + quot:= (others =>'0'); + TOPBIT:=0; + for j in DENOM'range loop + if DENOM(j)='1' then + TOPBIT:=j; + exit; + end if; + end loop; + + CARRY:='0'; + for j in num'length-(TOPBIT+1) downto 0 loop + -- lexical ordering works okay for this comparison, no overloaded + -- function is needed. + if CARRY&TEMP(TOPBIT+j downto j) >= "0"&DENOM(TOPBIT downto 0) then + diff(TOPBIT+1 downto 0) := (CARRY&TEMP(TOPBIT+j downto j)) + -("0"&DENOM(TOPBIT downto 0)); + + assert diff(TOPBIT+1)='0' + report "internal error in the division algorithm" + severity error; + CARRY:=diff(TOPBIT); + if TOPBIT+j+1<=TEMP'left then + TEMP(TOPBIT+j+1):='0'; + end if; + TEMP(TOPBIT+j downto j):=diff(TOPBIT downto 0); + quot(j):='1'; + else + assert CARRY='0' + report "internal error in the division algorithm" + severity error; + CARRY:=TEMP(TOPBIT+j); + end if; + end loop; + xquot:=quot(num'length-1 downto 0); + xremain:=TEMP(num'length-1 downto 0); + end divMod; + +-----------------Local Subprograms - shift/rotate ops------------------------- + +function XSLL(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := (others=>'0'); +begin + if COUNT <= ARG_L then + RESULT(ARG_L downto COUNT):=XARG(ARG_L-COUNT downto 0); + end if; + return RESULT; +end; + +function XSRL(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := (others=>'0'); +begin + if COUNT <= ARG_L then + RESULT(ARG_L-COUNT downto 0):=XARG(ARG_L downto COUNT); + end if; + return RESULT; +end; + +function XSRA(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0); +variable XCOUNT: natural := COUNT; +begin + if ((ARG'length <= 1) or (xCOUNT = 0)) then return ARG; + else + if (XCOUNT > ARG_L) then xCOUNT:= ARG_L; end if; + RESULT(ARG_L-XCOUNT downto 0):=XARG(ARG_L downto XCOUNT); + RESULT(ARG_L downto (ARG_L - XCOUNT + 1)) := (others=>XARG(ARG_L)); + end if; + return RESULT; + end; + +function XROL(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := XARG; +variable COUNTM: INTEGER; +begin + COUNTM:= COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L downto COUNTM):=XARG(ARG_L-COUNTM downto 0); + RESULT(COUNTM-1 downto 0):=XARG(ARG_L downto ARG_L-COUNTM+1); + end if; + return RESULT; + end; + +function XROR(ARG: STD_LOGIC_VECTOR; COUNT: NATURAL) return STD_LOGIC_VECTOR is +constant ARG_L:INTEGER:= ARG'length-1; +alias XARG: STD_LOGIC_VECTOR(ARG_L downto 0) is ARG; +variable RESULT: STD_LOGIC_VECTOR(ARG_L downto 0) := XARG; +variable COUNTM: INTEGER; +begin + COUNTM:= COUNT mod (ARG_L + 1); + if COUNTM /= 0 then + RESULT(ARG_L-COUNTM downto 0):=XARG(ARG_L downto COUNTM); + RESULT(ARG_L downto ARG_L-COUNTM+1):=XARG(COUNTM-1 downto 0); + end if; + return RESULT; + end; + + +-----------------Local Subprograms - Relational ops-------------------------- + +-- +-- General "=" for UNSIGNED vectors, same length +-- +function UNSIGNED_equal ( L,R: UNSIGNED) return BOOLEAN is +begin + return STD_LOGIC_VECTOR (L) = STD_LOGIC_VECTOR (R) ; + end; + +-- +-- General "=" for SIGNED vectors, same length +-- +function SIGNED_equal ( L,R: SIGNED) return BOOLEAN is +begin + return STD_LOGIC_VECTOR (L) = STD_LOGIC_VECTOR (R) ; + end; + + + +-- +-- General "<" for UNSIGNED vectors, same length +-- +function UNSIGNED_LESS ( L,R: UNSIGNED) return BOOLEAN is +begin + return STD_LOGIC_VECTOR (L) < STD_LOGIC_VECTOR (R) ; + end UNSIGNED_LESS ; + +-- +-- General "<" function for SIGNED vectors, same length +-- +function SIGNED_LESS ( L,R: SIGNED) return BOOLEAN is +variable intern_l : SIGNED (0 to L'LENGTH-1); +variable intern_r : SIGNED (0 to R'LENGTH-1); +begin + intern_l:=l; + intern_r:=r; + intern_l(0):=not intern_l(0); + intern_r(0):=not intern_r(0); + return STD_LOGIC_VECTOR (intern_L) < STD_LOGIC_VECTOR (intern_R) ; +end; + +-- +-- General "<=" function for UNSIGNED vectors, same length +-- +function UNSIGNED_LESS_OR_EQUAL ( L,R: UNSIGNED) return BOOLEAN is +begin + return STD_LOGIC_VECTOR (L) <= STD_LOGIC_VECTOR (R) ; + end; + +-- +-- General "<=" function for SIGNED vectors, same length +-- +function SIGNED_LESS_OR_EQUAL ( L,R: SIGNED) return BOOLEAN is + -- Need aliasses to assure index direction +variable intern_l : SIGNED (0 to L'LENGTH-1); +variable intern_r : SIGNED (0 to R'LENGTH-1); +begin + intern_l:=l; + intern_r:=r; + intern_l(0):=not intern_l(0); + intern_r(0):=not intern_r(0); + return STD_LOGIC_VECTOR (intern_L) <= STD_LOGIC_VECTOR (intern_R) ; + end; + +-- function TO_01 is used to convert vectors to the +-- correct form for exported functions, +-- and to report if there is an element which +-- is not in (0,1,h,l). +-- Assume the vector is normalized and non-null. +-- The function is duplicated for SIGNED and UNSIGNED types. + +function TO_01(S : SIGNED ; xmap : STD_LOGIC:= '0') return SIGNED is +variable RESULT: SIGNED(S'length-1 downto 0); +variable bad_element : boolean := FALSE; +alias xs : SIGNED(s'length-1 downto 0) is S; +begin + for i in RESULT'range loop + case xs(i) is + when '0' | 'L' => RESULT(i):='0'; + when '1' | 'H' => RESULT(i):='1'; + when others => bad_element := TRUE; + end case; + end loop; + if bad_element then + assert NO_WARNING + report "numeric_std.TO_01: Array Element not in {0,1,H,L}" + severity warning; + for i in RESULT'range loop + RESULT(i) := xmap; -- standard fixup + end loop; + end if; + return RESULT; + end TO_01; + +function TO_01(S : UNSIGNED ; xmap : STD_LOGIC:= '0') return UNSIGNED is +variable RESULT: UNSIGNED(S'length-1 downto 0); +variable bad_element : boolean := FALSE; +alias xs : UNSIGNED(S'length-1 downto 0) is S; +begin + for i in RESULT'range loop + case xs(i) is + when '0' | 'L' => RESULT(i):='0'; + when '1' | 'H' => RESULT(i):='1'; + when others => bad_element := TRUE; + end case; + end loop; + if bad_element then + assert NO_WARNING + report "numeric_std.TO_01: Array Element not in {0,1,H,L}" + severity warning; + for i in RESULT'range loop + RESULT(i) := xmap; -- standard fixup + end loop; + end if; + return RESULT; + end TO_01; + +--=========================Exported Functions================================= + + -- Id: A.1 +function "abs" ( X : SIGNED) return SIGNED is +constant ARG_LEFT:INTEGER:= X'length-1; +alias XX : SIGNED(ARG_LEFT downto 0) is X; +variable RESULT: SIGNED (ARG_LEFT downto 0); +begin + if X'length<1 then return NAS; end if; + RESULT:=TO_01(xx,'X'); + if (RESULT(RESULT'left)='X') then return RESULT; end if; + if RESULT(RESULT'left) = '1' then + RESULT:= -RESULT; + end if; + return RESULT; + end; -- "abs" + + + -- Id: A.2 +function "-" ( ARG: SIGNED) return SIGNED is +constant ARG_LEFT:INTEGER:= ARG'length-1; +alias XARG: SIGNED(ARG_LEFT downto 0) is ARG; +variable RESULT,XARG01 : SIGNED(ARG_LEFT downto 0); +variable CBIT : STD_LOGIC:= '1'; +begin + if ARG'length<1 then return NAS; end if; + XARG01 := TO_01(ARG,'X'); + if (XARG01(XARG01'left)='X') then return XARG01; end if; + for i in 0 to RESULT'left loop + RESULT(i) := not(XARG01(i)) xor CBIT; + CBIT := CBIT and not(XARG01(i)); + end loop; + return RESULT; + end; -- "-" + + +--============================================================================= + + + -- Id: A.3 +function "+" ( L,R: UNSIGNED ) return UNSIGNED is +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(SIZE-1 downto 0); +variable R01 : UNSIGNED(SIZE-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + L01 := TO_01(RESIZE(L,SIZE),'X'); + if (L01(L01'left)='X') then return L01; end if; + R01 := TO_01(RESIZE(R,SIZE),'X'); + if (R01(R01'left)='X') then return R01; end if; + return ADD_UNSIGNED (L01, R01, '0') ; + end; + + -- Id: A.4 +function "+" ( L,R: SIGNED ) return SIGNED is +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(SIZE-1 downto 0); +variable R01 : SIGNED(SIZE-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + L01 := TO_01(RESIZE(L,SIZE),'X'); + if (L01(L01'left)='X') then return L01; end if; + R01 := TO_01(RESIZE(R,SIZE),'X'); + if (R01(R01'left)='X') then return R01; end if; + return ADD_SIGNED (L01, R01, '0') ; + end; + + -- Id: A.5 +function "+" ( L: UNSIGNED; R: NATURAL) return UNSIGNED is +begin + return L + TO_UNSIGNED( R , L'length); + end; + + -- Id: A.6 +function "+" ( L: NATURAL; R: UNSIGNED) return UNSIGNED is +begin + return TO_UNSIGNED( L , R'length) + R; + end; + + -- Id: A.7 +function "+" ( L: SIGNED; R: INTEGER) return SIGNED is +begin + return L + TO_SIGNED( R , L'length); + end; + + -- Id: A.8 +function "+" ( L: INTEGER; R: SIGNED) return SIGNED is +begin + return TO_SIGNED( L , R'length) + R; + end; + +--============================================================================= + + -- Id: A.9 +function "-" ( L,R: UNSIGNED) return UNSIGNED is +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(SIZE-1 downto 0); +variable R01 : UNSIGNED(SIZE-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + L01 := TO_01(RESIZE(L,SIZE),'X'); + if (L01(L01'left)='X') then return L01; end if; + R01 := TO_01(RESIZE(R,SIZE),'X'); + if (R01(R01'left)='X') then return R01; end if; + return ADD_UNSIGNED (L01,not(R01),'1'); + end; + + -- Id: A.10 +function "-" ( L,R: SIGNED) return SIGNED is +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(SIZE-1 downto 0); +variable R01 : SIGNED(SIZE-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + L01 := TO_01(RESIZE(L,SIZE),'X'); + if (L01(L01'left)='X') then return L01; end if; + R01 := TO_01(RESIZE(R,SIZE),'X'); + if (R01(R01'left)='X') then return R01; end if; + return ADD_SIGNED (L01,not(R01),'1'); + end; + + + + -- Id: A.11 +function "-" ( L: UNSIGNED; R: NATURAL) return UNSIGNED is +begin + return L - TO_UNSIGNED( R , L'length); + end; + + -- Id: A.12 +function "-" ( L: NATURAL; R: UNSIGNED) return UNSIGNED is +begin + return TO_UNSIGNED( L , R'length) - R; + end; + + -- Id: A.13 +function "-" ( L: SIGNED; R: INTEGER) return SIGNED is +begin + return L - TO_SIGNED( R , L'length); + end; + + -- Id: A.14 +function "-" ( L: INTEGER; R: SIGNED) return SIGNED is +begin + return TO_SIGNED( L , R'length) - R ; + end; + + +--============================================================================= + + -- Id: A.15 +function "*" ( L,R: UNSIGNED) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : UNSIGNED(L_left downto 0) is L; +alias xxr : UNSIGNED(R_left downto 0) is R; +variable xl : UNSIGNED(L_left downto 0); +variable xr : UNSIGNED(R_left downto 0); +variable RESULT: UNSIGNED((L'length+R'length-1) downto 0) :=(others=>'0'); +variable adval : UNSIGNED((L'length+R'length-1) downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + RESULT:= (others=>'X'); + return RESULT; + end if; + adval := RESIZE(xr,RESULT'length); + for i in 0 to L_left loop + if xl(i)='1' then RESULT:= RESULT + adval; + end if; + adval := shift_left(adval,1); + end loop; + return RESULT; +end; + + -- Id: A.16 +function "*" ( L,R: SIGNED) return SIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : SIGNED(L_left downto 0) is L; +alias xxr : SIGNED(R_left downto 0) is R; +variable xl : SIGNED(L_left downto 0); +variable xr : SIGNED(R_left downto 0); +variable RESULT: SIGNED((L'length+R'length-1) downto 0) :=(others=>'0'); +variable adval : SIGNED((L'length+R'length-1) downto 0); +variable invt : STD_LOGIC:= '0'; +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + RESULT:= (others=>'X'); + return RESULT; + end if; + adval := RESIZE(xr,RESULT'length); + if xl(xl'left)='1' then + adval := -(adval); + invt := '1'; + end if; + for i in 0 to L_left loop + if (invt xor xl(i))='1' then RESULT:= RESULT + adval; + end if; + adval := shift_left(adval,1); + end loop; + return RESULT; + end; + + + -- Id: A.17 +function "*" ( L: UNSIGNED; R: NATURAL) return UNSIGNED is +begin + return L * TO_UNSIGNED( R , L'length); + end; + + -- Id: A.18 +function "*" ( L: NATURAL; R: UNSIGNED) return UNSIGNED is +begin + return TO_UNSIGNED( L , R'length) * R; + end; + + -- Id: A.19 +function "*" ( L: SIGNED; R: INTEGER) return SIGNED is +begin + return L * TO_SIGNED( R , L'length); + end; + + -- Id: A.20 +function "*" ( L: INTEGER; R: SIGNED) return SIGNED is +begin + return TO_SIGNED( L , R'length) * R ; + end; + +--============================================================================= + + -- Id: A.21 +function "/" ( L,R: UNSIGNED) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : UNSIGNED(L_left downto 0) is L; +alias xxr : UNSIGNED(R_left downto 0) is R; +variable xl : UNSIGNED(L_left downto 0); +variable xr : UNSIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(L'length-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fquot := (others=>'X'); + return fquot; + end if; + divMod(xl,xr,fquot,fremain); + return fquot; + end; + + -- Id: A.22 +function "/" ( L,R: SIGNED) return SIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : SIGNED(L_left downto 0) is L; +alias xxr : SIGNED(R_left downto 0) is R; +variable xl : SIGNED(L_left downto 0); +variable xr : SIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(L'length-1 downto 0); +variable xnum: UNSIGNED(L'length-1 downto 0); +variable XDENOM: UNSIGNED(R'length-1 downto 0); +variable qneg: boolean := FALSE; +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fquot := (others=>'X'); + return SIGNED(fquot); + end if; + if xl(xl'left)='1' then + xnum:=UNSIGNED(-xl); + qNeg:=TRUE; + else + xnum:=UNSIGNED(xl); + end if; + if xr(xr'left)='1' then + xdenom:=UNSIGNED(-xr); + qNeg:=not qNeg; + else + xdenom:=UNSIGNED(xr); + end if; + divMod(xnum,XDENOM,fquot,fremain); + if qNeg then fquot:="0"-fquot; end if; + return SIGNED(fquot); + end; + + -- Id: A.23 +function "/" ( L : UNSIGNED; R : NATURAL) return UNSIGNED is + constant R_Length : Natural := max(L'Length, unsigned_num_bits(R)); + variable XR,Quot : unsigned (R_Length-1 downto 0); +begin + XR := TO_UNSIGNED(R, R_Length); + Quot := L / XR; + if R_Length>L'Length and Quot(0)/='X' + and Quot(R_Length-1 downto L'Length)/=(R_Length-1 downto L'Length => '0') + then + ASSERT no_warning report "Numeric_std.""/"": Quotient Truncated" + severity warning; + end if; + return Quot(L'Length-1 downto 0); + end; + + -- Id: A.24 +function "/" ( L : NATURAL; R : UNSIGNED) return UNSIGNED is + constant L_Length : Natural := max(unsigned_num_bits(L), R'length); + variable XL,Quot : UNSIGNED (L_Length-1 downto 0); +begin + XL := TO_UNSIGNED(L,L_LENGTH); + QUOT := XL / R; + if L_LENGTH>R'LENGTH and Quot(0)/='X' + and QUOT(L_LENGTH-1 downto R'Length)/=(L_LENGTH-1 downto R'Length => '0') + then + ASSERT no_warning report "Numeric_std.""/"": Quotient Truncated" + severity warning; + end if; + return Quot(R'Length-1 downto 0); + end; + + -- Id: A.25 +function "/" ( L : SIGNED; R : INTEGER ) return SIGNED is + constant R_Length : Natural := max(L'Length, signed_num_bits(R)); + variable XR,Quot : signed (R_Length-1 downto 0); +begin + XR := TO_SIGNED(R, R_Length); + Quot := L / XR; + if R_Length>L'Length and Quot(0)/='X' + and Quot(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => Quot(L'Length-1)) + then + ASSERT no_warning report "Numeric_std.""/"": Quotient Truncated" + severity warning; + end if; + return Quot(L'Length-1 downto 0); + end; + + -- Id: A.26 +function "/" ( L : INTEGER; R : SIGNED) return SIGNED is + constant L_Length : Natural := max(signed_num_bits(L), R'length); + variable XL,Quot : SIGNED (L_Length-1 downto 0); +begin + XL := TO_SIGNED(L,L_LENGTH); + QUOT := XL / R; + if L_LENGTH>R'LENGTH and Quot(0)/='X' + and QUOT(L_LENGTH-1 downto R'Length) + /= (L_LENGTH-1 downto R'Length => Quot(R'Length-1)) + then + ASSERT no_warning report "Numeric_std.""/"": Quotient Truncated" + severity warning; + end if; + return Quot(R'Length-1 downto 0); + end; +--============================================================================= + + -- Id: A.27 +function "rem" ( L,R: UNSIGNED) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : UNSIGNED(L_left downto 0) is L; +alias xxr : UNSIGNED(R_left downto 0) is R; +variable xl : UNSIGNED(L_left downto 0); +variable xr : UNSIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(l'length-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fremain := (others=>'X'); + return fremain; + end if; + divMod(xl,xr,fquot,fremain); + return fremain; + end; + + -- Id: A.28 +function "rem" ( L,R: SIGNED) return SIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : SIGNED(L_left downto 0) is L; +alias xxr : SIGNED(R_left downto 0) is R; +variable fquot,fremain : UNSIGNED(l'length-1 downto 0); +variable xnum: UNSIGNED(l'length-1 downto 0); +variable XDENOM: UNSIGNED(r'length-1 downto 0); +variable rneg: boolean := FALSE; +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + xnum := UNSIGNED(TO_01(xxl,'X')); + XDENOM := UNSIGNED(TO_01(xxr,'X')); + if ((xnum(xnum'left)='X') or (xdenom(xnum'left)='X')) then + fremain := (others=>'X'); + return SIGNED(fremain); + end if; + if xnum(xnum'left)='1' then + xnum:=UNSIGNED(-SIGNED(xnum)); + rNeg:=TRUE; + else + xNum:=UNSIGNED(xnum); + end if; + if XDENOM(XDENOM'left)='1' then + XDENOM:=UNSIGNED(-SIGNED(XDENOM)); + else + XDENOM:=UNSIGNED(XDENOM); + end if; + divMod(xnum,XDENOM,fquot,fremain); + if rNeg then + fremain:="0"-fremain; + end if; + return SIGNED(fremain); + end; + + -- Id: A.29 +function "rem" ( L : UNSIGNED; R : NATURAL) return UNSIGNED is + constant R_Length : Natural := max(L'Length, unsigned_num_bits(R)); + variable XR,XRem : unsigned (R_Length-1 downto 0); +begin + XR := TO_UNSIGNED(R, R_Length); + XRem := L rem XR; + if R_Length>L'Length and XRem(0)/='X' + and XRem(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => '0') + then + ASSERT no_warning report "Numeric_std.""rem"": Remainder Truncated" + severity warning; + end if; + return XRem(L'Length-1 downto 0); +end; + + -- Id: A.30 +function "rem" ( L : NATURAL; R : UNSIGNED) return UNSIGNED is + constant L_Length : Natural := max(unsigned_num_bits(L), R'Length); + variable XL,XRem : unsigned (L_Length-1 downto 0); +begin + XL := TO_UNSIGNED(L, L_Length); + XRem := XL rem R; + if L_Length>R'Length and XRem(0)/='X' + and XRem(L_Length-1 downto R'Length) + /= (L_Length-1 downto R'Length => '0') + then + ASSERT no_warning report "Numeric_std.""rem"": Remainder Truncated" + severity warning; + end if; + return XRem(R'Length-1 downto 0); +end; + + -- Id: A.31 +function "rem" ( L : SIGNED; R : INTEGER ) return SIGNED is + constant R_Length : Natural := max(L'Length, signed_num_bits(R)); + variable XR,XRem : signed (R_Length-1 downto 0); +begin + XR := TO_SIGNED(R, R_Length); + XRem := L rem XR; + if R_Length>L'Length and XRem(0)/='X' + and XRem(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => XRem(L'Length-1)) + then + ASSERT no_warning report "Numeric_std.""rem"": Remainder Truncated" + severity warning; + end if; + return XRem(L'Length-1 downto 0); +end; + + -- Id: A.32 +function "rem" ( L : INTEGER; R : SIGNED) return SIGNED is + constant L_Length : Natural := max(signed_num_bits(L), R'Length); + variable XL,XRem : signed (L_Length-1 downto 0); +begin + XL := TO_SIGNED(L, L_Length); + XRem := XL rem R; + if L_Length>R'Length and XRem(0)/='X' + and XRem(L_Length-1 downto R'Length) + /= (L_Length-1 downto R'Length => XRem(R'Length-1)) + then + ASSERT no_warning report "Numeric_std.""rem"": Remainder Truncated" + severity warning; + end if; + return XRem(R'Length-1 downto 0); +end; + +--============================================================================= + + -- Id: A.33 +function "mod" ( L,R: UNSIGNED) return UNSIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : UNSIGNED(L_left downto 0) is L; +alias xxr : UNSIGNED(R_left downto 0) is R; +variable xl : UNSIGNED(L_left downto 0); +variable xr : UNSIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(l'length-1 downto 0); +begin + if ((L'length<1) or (R'length<1)) then return NAU; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fremain := (others=>'X'); + return fremain; + end if; + divMod(xl,xr,fquot,fremain); + return fremain; + end; + + -- Id: A.34 +function "mod" ( L,R: SIGNED) return SIGNED is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias xxl : SIGNED(L_left downto 0) is L; +alias xxr : SIGNED(R_left downto 0) is R; +variable xl : SIGNED(L_left downto 0); +variable xr : SIGNED(R_left downto 0); +variable fquot,fremain : UNSIGNED(l'length-1 downto 0); +variable xnum: UNSIGNED(l'length-1 downto 0); +variable XDENOM: UNSIGNED(r'length-1 downto 0); +variable rneg: boolean := FALSE; +begin + if ((L'length<1) or (R'length<1)) then return NAS; end if; + xl := TO_01(xxl,'X'); + xr := TO_01(xxr,'X'); + if ((xl(xl'left)='X') or (xr(xr'left)='X')) then + fremain := (others=>'X'); + return SIGNED(fremain); + end if; + if xl(xl'left)='1' then + xnum:=UNSIGNED(-xl); + else + xNum:=UNSIGNED(xl); + end if; + if xr(xr'left)='1' then + XDENOM:=UNSIGNED(-xr); + rNeg:=TRUE; + else + XDENOM:=UNSIGNED(xr); + end if; + divMod(xnum,XDENOM,fquot,fremain); + if rNeg and l(l'left)='1' then + fremain:="0"-fremain; + elsif rNeg then + fremain:=fremain-XDENOM; + elsif l(l'left)='1' then + fremain:=XDENOM-fremain; + end if; + return SIGNED(fremain); + end; + + -- Id: A.35 +function "mod" ( L : UNSIGNED; R : NATURAL) return UNSIGNED is + constant R_Length : Natural := max(L'Length, unsigned_num_bits(R)); + variable XR,XRem : unsigned (R_Length-1 downto 0); +begin + XR := TO_UNSIGNED(R, R_Length); + XRem := L mod XR; + if R_Length>L'Length and XRem(0)/='X' + and XRem(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => '0') + then + ASSERT no_warning report "Numeric_std.""mod"": Modulus Truncated" + severity warning; + end if; + return XRem(L'Length-1 downto 0); +end; + + -- Id: A.36 +function "mod" ( L : NATURAL; R : UNSIGNED) return UNSIGNED is + constant L_Length : Natural := max(unsigned_num_bits(L), R'Length); + variable XL,XRem : unsigned (L_Length-1 downto 0); +begin + XL := TO_UNSIGNED(L, L_Length); + XRem := XL mod R; + if L_Length>R'Length and XRem(0)/='X' + and XRem(L_Length-1 downto R'Length) + /= (L_Length-1 downto R'Length => '0') + then + ASSERT no_warning report "Numeric_std.""mod"": Modulus Truncated" + severity warning; + end if; + return XRem(R'Length-1 downto 0); +end; + + -- Id: A.37 +function "mod" ( L : SIGNED; R : INTEGER ) return SIGNED is + constant R_Length : Natural := max(L'Length, signed_num_bits(R)); + variable XR,XRem : signed (R_Length-1 downto 0); +begin + XR := TO_SIGNED(R, R_Length); + XRem := L mod XR; + if R_Length>L'Length and XRem(0)/='X' + and XRem(R_Length-1 downto L'Length) + /= (R_Length-1 downto L'Length => XRem(L'Length-1)) + then + ASSERT no_warning report "Numeric_std.""mod"": Modulus Truncated" + severity warning; + end if; + return XRem(L'Length-1 downto 0); +end; + + -- Id: A.38 +function "mod" ( L : INTEGER; R : SIGNED) return SIGNED is + constant L_Length : Natural := max(signed_num_bits(L), R'Length); + variable XL,XRem : signed (L_Length-1 downto 0); +begin + XL := TO_SIGNED(L, L_Length); + XRem := XL mod R; + if L_Length>R'Length and XRem(0)/='X' + and XRem(L_Length-1 downto R'Length) + /= (L_Length-1 downto R'Length => XRem(R'Length-1)) + then + ASSERT no_warning report "Numeric_std.""mod"": Modulus Truncated" + severity warning; + end if; + return XRem(R'Length-1 downto 0); +end; + +--============================================================================= + + -- Id: C.1 +function ">" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return not UNSIGNED_LESS_OR_EQUAL (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end ">" ; + + -- Id: C.2 +function ">" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return not SIGNED_LESS_OR_EQUAL (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end ">" ; + + -- Id: C.3 +function ">" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(l)>R'length then return TRUE; end if; + return not UNSIGNED_LESS_OR_EQUAL (TO_UNSIGNED (L,R01'LENGTH), R01) ; + end ">" ; + + -- Id: C.4 +function ">" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(l)>R'length then return L>0; end if; + return not SIGNED_LESS_OR_EQUAL (TO_SIGNED(L,R01'LENGTH), R01) ; + end ">" ; + + -- Id: C.5 +function ">" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return FALSE; end if; + return not UNSIGNED_LESS_OR_EQUAL (L01, TO_UNSIGNED (R,L01'LENGTH)) ; + end ">" ; + + -- Id: C.6 +function ">" ( L: SIGNED; R: INTEGER) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +variable L01 : SIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(R)>L'length then return 0>R; end if; + return not SIGNED_LESS_OR_EQUAL (L01, TO_SIGNED(R,L01'LENGTH)) ; + end ">" ; + +--============================================================================= + + -- Id: C.7 +function "<" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return UNSIGNED_LESS (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end "<" ; + + -- Id: C.8 +function "<" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return SIGNED_LESS (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end "<" ; + + -- Id: C.9 +function "<" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(L)>R'length then return L<0; end if; + return UNSIGNED_LESS (TO_UNSIGNED(L,R01'LENGTH), R01) ; + end "<" ; + + -- Id: C.10 +function "<" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(L)>R'length then return L<0; end if; + return SIGNED_LESS (TO_SIGNED(L,R01'LENGTH), R01) ; + end "<" ; + + -- Id: C.11 +function "<" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return 0L'length then return 0=" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return not UNSIGNED_LESS (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end ">=" ; + + -- Id: C.20 +function ">=" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return not SIGNED_LESS (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end ">=" ; + + -- Id: C.21 +function ">=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(L)>R'length then return L>0; end if; + return not UNSIGNED_LESS (TO_UNSIGNED(L,R01'LENGTH), R01) ; + end ">=" ; + + -- Id: C.22 +function ">=" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(L)>R'length then return L>0; end if; + return not SIGNED_LESS (TO_SIGNED (L,R01'LENGTH), R01) ; + end ">=" ; + + -- Id: C.23 +function ">=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return 0>R; end if; + return not UNSIGNED_LESS(L01, TO_UNSIGNED(R,L01'LENGTH)) ; + end ">=" ; + + -- Id: C.24 +function ">=" ( L: SIGNED; R: INTEGER) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +variable L01 : SIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if Signed_NUM_BITS(R)>L'length then return 0>R; end if; + return not SIGNED_LESS (L01, TO_SIGNED(R,L01'LENGTH)) ; + end ">=" ; + +--============================================================================= + + -- Id: C.25 +function "=" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return UNSIGNED_equal (RESIZE(L01,SIZE),RESIZE(R01,SIZE)) ; + end "=" ; + + -- Id: C.26 +function "=" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL,'X'); + R01 := TO_01(XR,'X'); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return FALSE; end if; + return SIGNED_equal (RESIZE(L01,SIZE), RESIZE(R01,SIZE)) ; + end "=" ; + + -- Id: C.27 +function "=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(L)>R'Length then return FALSE; end if; + return UNSIGNED_equal ( TO_UNSIGNED(L,R01'LENGTH), R01); + end "=" ; + + -- Id: C.28 +function "=" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR,'X'); + if (R01(R01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(L)>R'Length then return FALSE; end if; + return SIGNED_equal ( TO_SIGNED(L,R01'LENGTH), R01) ; + end "=" ; + + -- Id: C.29 +function "=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return FALSE; end if; + return UNSIGNED_equal (L01, TO_UNSIGNED (R,L01'LENGTH)) ; + end "=" ; + + -- Id: C.30 +function "=" ( L: SIGNED; R: INTEGER) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +variable L01 : SIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL,'X'); + if (L01(L01'left)='X') then return FALSE; end if; + if UNSIGNED_NUM_BITS(R)>L'length then return FALSE; end if; + return SIGNED_equal (L01, TO_SIGNED (R,L01'LENGTH)) ; + end "=" ; + + +--============================================================================= + + -- Id: C.31 +function "/=" ( L,R: UNSIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +alias XR: UNSIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : UNSIGNED(L_left downto 0); +variable R01 : UNSIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL); + R01 := TO_01(XR); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return TRUE; end if; + return not(UNSIGNED_equal (RESIZE(L01,SIZE),RESIZE(R01,SIZE))) ; + end "/=" ; + + -- Id: C.32 +function "/=" ( L,R: SIGNED) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +constant R_left:INTEGER:= R'length-1; +alias XL: SIGNED(L_left downto 0) is L; +alias XR: SIGNED(R_left downto 0) is R; +constant SIZE: NATURAL:= MAX (L'LENGTH, R'LENGTH) ; +variable L01 : SIGNED(L_left downto 0); +variable R01 : SIGNED(R_left downto 0); +begin + if ((L'length<1) or (R'length<1)) then return FALSE; end if; + L01 := TO_01(XL); + R01 := TO_01(XR); + if ((L01(L01'left)='X') or (R01(R01'left)='X')) then return TRUE; end if; + return not(SIGNED_equal (RESIZE(L01,SIZE), RESIZE(R01,SIZE))) ; + end "/=" ; + + -- Id: C.33 +function "/=" ( L: NATURAL; R: UNSIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: UNSIGNED(R_left downto 0) is R; +variable R01 : UNSIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR); + if (R01(R01'left)='X') then return TRUE; end if; + if UNSIGNED_NUM_BITS(L)>R'Length then return TRUE; end if; + return not(UNSIGNED_equal ( TO_UNSIGNED(L,R01'LENGTH), R01)); + end "/=" ; + + -- Id: C.34 +function "/=" ( L: INTEGER; R: SIGNED) return BOOLEAN is +constant R_left:INTEGER:= R'length-1; +alias XR: SIGNED(R_left downto 0) is R; +variable R01 : SIGNED(R_left downto 0); +begin + if (R'length<1) then return FALSE; end if; + R01 := TO_01(XR); + if (R01(R01'left)='X') then return TRUE; end if; + if Signed_NUM_BITS(L)>R'Length then return TRUE; end if; + return not(SIGNED_equal ( TO_SIGNED(L,R01'LENGTH), R01)) ; + end "/=" ; + + -- Id: C.35 +function "/=" ( L: UNSIGNED; R: NATURAL) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: UNSIGNED(L_left downto 0) is L; +variable L01 : UNSIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL); + if (L01(L01'left)='X') then return TRUE; end if; + if UNSIGNED_NUM_BITS(R)>L'Length then return TRUE; end if; + return not(UNSIGNED_equal (L01, TO_UNSIGNED (R,L01'LENGTH))) ; + end "/=" ; + + -- Id: C.36 +function "/=" ( L: SIGNED; R: INTEGER) return BOOLEAN is +constant L_left:INTEGER:= L'length-1; +alias XL: SIGNED(L_left downto 0) is L; +variable L01 : SIGNED(L_left downto 0); +begin + if (L'length<1) then return FALSE; end if; + L01 := TO_01(XL); + if (L01(L01'left)='X') then return TRUE; end if; + if Signed_NUM_BITS(R)>L'Length then return TRUE; end if; + return not(SIGNED_equal (L01, TO_SIGNED (R,L01'LENGTH))) ; + end "/=" ; + + +--============================================================================= + + -- Id: S.1 +function shift_left(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is +begin + if (ARG'length<1) then return NAU; end if; + return UNSIGNED(XSLL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.2 +function shift_right(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is +begin + if (ARG'length<1) then return NAU; end if; + return UNSIGNED(XSRL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.3 +function shift_left(ARG: SIGNED; COUNT: NATURAL) return SIGNED is +begin + if (ARG'length<1) then return NAS; end if; + return SIGNED(XSLL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.4 +function shift_right(ARG: SIGNED; COUNT: NATURAL) return SIGNED is +begin + if (ARG'length<1) then return NAS; end if; + return SIGNED(XSRA(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + +--============================================================================= + + -- Id: S.5 +function rotate_left(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is +begin + if (ARG'length<1) then return NAU; end if; + return UNSIGNED(XROL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.6 +function rotate_right(ARG: UNSIGNED; COUNT: NATURAL) return UNSIGNED is +begin + if (ARG'length<1) then return NAU; end if; + return UNSIGNED(XROR(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + + -- Id: S.7 +function rotate_left(ARG: SIGNED; COUNT: NATURAL) return SIGNED is +begin + if (ARG'length<1) then return NAS; end if; + return SIGNED(XROL(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + + -- Id: S.8 +function rotate_right(ARG: SIGNED; COUNT: NATURAL) return SIGNED is +begin + if (ARG'length<1) then return NAS; end if; + return SIGNED(XROR(STD_LOGIC_VECTOR(ARG),COUNT)); + end; + +--============================================================================= + + + -- Id: D.1 +function TO_INTEGER(ARG: UNSIGNED) return NATURAL is +constant ARG_LEFT:INTEGER:= ARG'length-1; +alias XXARG:UNSIGNED(ARG_LEFT downto 0) is ARG; +variable XARG:UNSIGNED(ARG_LEFT downto 0); +variable RESULT: NATURAL:= 0; +variable w : INTEGER:= 1; -- weight factor +begin + if (ARG'length<1) then + assert NO_WARNING + report "numeric_std.TO_INTEGER: null arg" + severity warning; + return 0; + end if; + XARG:= TO_01(XXARG); + if (XARG(XARG'left)='X') then + assert NO_WARNING + report "numeric_std.TO_INTEGER: metavalue arg set to 0" + severity warning; + return 0; + end if; + for i in XARG'reverse_range loop + if XARG (i) = '1' then + RESULT:= RESULT + w; + end if; + if (i /= XARG'left) then w := w + w; + end if; + end loop; + return RESULT; + end TO_INTEGER; + + -- Id: D.2 +function TO_INTEGER(ARG: SIGNED) return INTEGER is +begin + if ARG(ARG'left) = '0' then + return TO_INTEGER( UNSIGNED (ARG)) ; + else + return (- (TO_INTEGER( UNSIGNED ( - (ARG + 1)))) -1); + end if; + end TO_INTEGER; + + -- Id: D.3 +function TO_UNSIGNED(ARG,SIZE: NATURAL) return UNSIGNED is + variable RESULT: UNSIGNED (SIZE-1 downto 0) ; + variable i_val:natural := ARG; + begin + if (SIZE < 1) then return NAU; end if; + for i in 0 to RESULT'left loop + if (i_val MOD 2) = 0 then + RESULT(i) := '0'; + else RESULT(i) := '1' ; + end if; + i_val := i_val/2 ; + end loop; + if not(i_val=0) then + assert NO_WARNING + report "numeric_std.TO_UNSIGNED : vector truncated" + severity WARNING ; + end if; + return RESULT ; + end TO_UNSIGNED; + + -- Id: D.4 +function TO_SIGNED(ARG: INTEGER; SIZE: NATURAL) return SIGNED is + variable RESULT: SIGNED (SIZE-1 downto 0) ; + variable b_val : STD_LOGIC:= '0' ; + variable i_val : INTEGER:= ARG ; + begin + if (SIZE < 1) then return NAS; end if; + if (ARG<0) then + b_val := '1' ; + i_val := -(ARG+1) ; + end if ; + for i in 0 to RESULT'left loop + if (i_val MOD 2) = 0 then + RESULT(i) := b_val; + else + RESULT(i) := not b_val ; + end if; + i_val := i_val/2 ; + end loop; + if ((i_val/=0) or (b_val/=RESULT(RESULT'left))) then + assert NO_WARNING + report "numeric_std.TO_SIGNED : vector truncated" + severity WARNING ; + end if; + return RESULT; + end TO_SIGNED; + + -- Id: D.5 +function TO_UNSIGNED(ARG: STD_LOGIC_VECTOR) return UNSIGNED is + begin + return UNSIGNED(ARG); + end TO_UNSIGNED; + + -- Id: D.6 +function TO_SIGNED(ARG: STD_LOGIC_VECTOR) return SIGNED is + begin + return SIGNED(ARG); + end TO_SIGNED; + + -- Id: D.7 +function TO_STDLOGICVECTOR(ARG: UNSIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(ARG); + end TO_STDLOGICVECTOR; + + -- Id: D.8 +function TO_STDLOGICVECTOR(ARG: SIGNED) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(ARG); + end TO_STDLOGICVECTOR; + +--============================================================================= + + + -- Id: R.1 +function RESIZE (ARG: SIGNED; NEW_SIZE: NATURAL) return SIGNED is +alias invec : SIGNED (ARG'length-1 downto 0) is ARG ; +variable RESULT: SIGNED (NEW_SIZE-1 downto 0) ; +constant bound : NATURAL:= MIN(ARG'length,RESULT'length)-2 ; +begin + if (NEW_SIZE<1) then return NAS; end if; + RESULT:= (others=>ARG(ARG'left)) ; + if bound >= 0 then + RESULT(bound downto 0) := invec(bound downto 0) ; + end if; + return RESULT; + end RESIZE ; + + + -- Id: R.2 +function RESIZE ( ARG: UNSIGNED; NEW_SIZE: NATURAL) return UNSIGNED is +constant ARG_LEFT:INTEGER:= ARG'length-1; +alias XARG: UNSIGNED(ARG_LEFT downto 0) is ARG; +variable RESULT: UNSIGNED(NEW_SIZE-1 downto 0) := (others=>'0'); +begin + if (NEW_SIZE<1) then return NAU; end if; + if XARG'length=0 then return RESULT; + end if; + if (RESULT'length < ARG'length) then + RESULT(RESULT'left downto 0) := XARG(RESULT'left downto 0); + else + RESULT(RESULT'left downto XARG'left+1) := (others => '0'); + RESULT(XARG'left downto 0) := XARG; + end if; + return RESULT; + end RESIZE; + + + --============================================================================ + + -- Id: L.1 +function "not" ( L: UNSIGNED) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(not(STD_LOGIC_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.2 +function "and" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) and STD_LOGIC_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.3 +function "or" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) or STD_LOGIC_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.4 +function "nand" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) nand STD_LOGIC_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.5 +function "nor" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) nor STD_LOGIC_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.6 +function "xor" ( L,R: UNSIGNED ) return UNSIGNED is +variable RESULT: UNSIGNED (L'range); +begin + RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) xor STD_LOGIC_VECTOR(R)); + return RESULT; + end "xor"; + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this 1076.3 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + -- Id: L.7 +--function "xnor" ( L,R: UNSIGNED ) return UNSIGNED is +--variable RESULT: UNSIGNED (L'range); +--begin +-- RESULT:= UNSIGNED(STD_LOGIC_VECTOR(L) xnor STD_LOGIC_VECTOR(R)); +-- return RESULT; +-- end "xnor"; + + -- Id: L.8 +function "not" ( L: SIGNED) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(not(STD_LOGIC_VECTOR(L))); + return RESULT; + end "not"; + + -- Id: L.9 +function "and" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) and STD_LOGIC_VECTOR(R)); + return RESULT; + end "and"; + + -- Id: L.10 +function "or" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) or STD_LOGIC_VECTOR(R)); + return RESULT; + end "or"; + + -- Id: L.11 +function "nand" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) nand STD_LOGIC_VECTOR(R)); + return RESULT; + end "nand"; + + -- Id: L.12 +function "nor" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) nor STD_LOGIC_VECTOR(R)); + return RESULT; + end "nor"; + + -- Id: L.13 +function "xor" ( L,R: SIGNED ) return SIGNED is +variable RESULT: SIGNED (L'range); +begin + RESULT:= SIGNED(STD_LOGIC_VECTOR(L) xor STD_LOGIC_VECTOR(R)); + return RESULT; + end "xor"; + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this 1076.3 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + -- Id: L.14 +--function "xnor" ( L,R: SIGNED ) return SIGNED is +--variable RESULT: SIGNED (L'range); +--begin +-- RESULT:= SIGNED(STD_LOGIC_VECTOR(L) xnor STD_LOGIC_VECTOR(R)); +-- return RESULT; +-- end "xnor"; + +--============================================================================= + +-- support constants for STD_MATCH: + + type STDULOGIC_TABLE is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; + + -- truth table for "and" function + constant AND_TABLE : STDULOGIC_TABLE := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -- | U | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 1 | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | Z | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | H | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ) -- | - | + ); + + -- truth table for STD_MATCH function + constant MATCH_TABLE : STDULOGIC_TABLE := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | X | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', '1' ), -- | 0 | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', '1' ), -- | 1 | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | Z | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1' ), -- | W | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', '1' ), -- | L | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', '1' ), -- | H | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ) -- | - | + ); + + -- Id: M.1 +function STD_MATCH (L, R: STD_ULOGIC) return BOOLEAN is + variable VALUE : STD_ULOGIC; + begin + VALUE := MATCH_TABLE(L, R); + return VALUE = '1'; + end STD_MATCH; + + + -- Id: M.2 +function STD_MATCH (L, R: STD_LOGIC_VECTOR) return BOOLEAN is + alias LV: STD_LOGIC_VECTOR ( 1 to L'LENGTH ) is L; + alias RV: STD_LOGIC_VECTOR ( 1 to R'LENGTH ) is R; + variable VALUE: STD_ULOGIC:= '1'; + begin + -- Check that both input vectors are the same length. + if LV'LENGTH /= RV'LENGTH then + assert NO_WARNING + report "STD_MATCH input arguments are not of equal length" + severity warning; + return FALSE; + else + for i in LV'LOW to LV'HIGH loop + VALUE := AND_TABLE(MATCH_TABLE(LV(i), RV(i)), VALUE); + end loop; + return VALUE = '1'; + end if; + end STD_MATCH; + + + +--============================================================================= +end numeric_std; + + + + diff --git a/lib/Standard/ieee/std_logic_1164.vhdl b/lib/Standard/ieee/std_logic_1164.vhdl new file mode 100644 index 0000000..5b165d2 --- /dev/null +++ b/lib/Standard/ieee/std_logic_1164.vhdl @@ -0,0 +1,178 @@ +-- -------------------------------------------------------------------- +-- +-- Title : std_logic_1164 multi-value logic system +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- Developers: IEEE model standards group (par 1164) +-- Purpose : This packages defines a standard for designers +-- : to use in describing the interconnection data types +-- : used in vhdl modeling. +-- : +-- Limitation: The logic system defined in this package may +-- : be insufficient for modeling switched transistors, +-- : since such a requirement is out of the scope of this +-- : effort. Furthermore, mathematics, primitives, +-- : timing standards, etc. are considered orthogonal +-- : issues as it relates to this package and are therefore +-- : beyond the scope of this effort. +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : std_logic_1164. The std_logic_1164 package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- -------------------------------------------------------------------- +-- modification history : +-- -------------------------------------------------------------------- +-- version | mod. date:| +-- v4.200 | 01/02/92 | +-- -------------------------------------------------------------------- + +PACKAGE std_logic_1164 IS + + ------------------------------------------------------------------- + -- logic state system (unresolved) + ------------------------------------------------------------------- + TYPE std_ulogic IS ( 'U', -- Uninitialized + 'X', -- Forcing Unknown + '0', -- Forcing 0 + '1', -- Forcing 1 + 'Z', -- High Impedance + 'W', -- Weak Unknown + 'L', -- Weak 0 + 'H', -- Weak 1 + '-' -- Don't care + ); + ------------------------------------------------------------------- + -- unconstrained array of std_ulogic for use with the resolution function + ------------------------------------------------------------------- + TYPE std_ulogic_vector IS ARRAY ( NATURAL RANGE <> ) OF std_ulogic; + + ------------------------------------------------------------------- + -- resolution function + ------------------------------------------------------------------- + FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic; + + ------------------------------------------------------------------- + -- *** industry standard logic type *** + ------------------------------------------------------------------- + SUBTYPE std_logic IS resolved std_ulogic; + + ------------------------------------------------------------------- + -- unconstrained array of std_logic for use in declaring signal arrays + ------------------------------------------------------------------- + TYPE std_logic_vector IS ARRAY ( NATURAL RANGE <>) OF std_logic; + + ------------------------------------------------------------------- + -- common subtypes + ------------------------------------------------------------------- + SUBTYPE X01 IS resolved std_ulogic RANGE 'X' TO '1'; -- ('X','0','1') + SUBTYPE X01Z IS resolved std_ulogic RANGE 'X' TO 'Z'; -- ('X','0','1','Z') + SUBTYPE UX01 IS resolved std_ulogic RANGE 'U' TO '1'; -- ('U','X','0','1') + SUBTYPE UX01Z IS resolved std_ulogic RANGE 'U' TO 'Z'; -- ('U','X','0','1','Z') + + ------------------------------------------------------------------- + -- overloaded logical operators + ------------------------------------------------------------------- + + FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + function "xnor" ( l : std_ulogic; r : std_ulogic ) return ux01; + FUNCTION "not" ( l : std_ulogic ) RETURN UX01; + + ------------------------------------------------------------------- + -- vectorized overloaded logical operators + ------------------------------------------------------------------- + FUNCTION "and" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "and" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "nand" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nand" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "or" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "or" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "nor" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "xor" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "xor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this std_logic_1164 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + function "xnor" ( l, r : std_logic_vector ) return std_logic_vector; + function "xnor" ( l, r : std_ulogic_vector ) return std_ulogic_vector; + + FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector; + + ------------------------------------------------------------------- + -- conversion functions + ------------------------------------------------------------------- + FUNCTION To_bit ( s : std_ulogic; xmap : BIT := '0') + RETURN BIT; + FUNCTION To_bitvector ( s : std_logic_vector ; xmap : BIT := '0') + RETURN BIT_VECTOR; + FUNCTION To_bitvector ( s : std_ulogic_vector; xmap : BIT := '0') + RETURN BIT_VECTOR; + + FUNCTION To_StdULogic (b : BIT ) RETURN std_ulogic; + FUNCTION To_StdLogicVector (b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_StdLogicVector (s : std_ulogic_vector) RETURN std_logic_vector; + FUNCTION To_StdULogicVector(b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_StdULogicVector(s : std_logic_vector) RETURN std_ulogic_vector; + + ------------------------------------------------------------------- + -- strength strippers and type convertors + ------------------------------------------------------------------- + + FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_X01 ( s : std_ulogic ) RETURN X01; + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_X01 ( b : BIT ) RETURN X01; + + FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z; + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_X01Z ( b : BIT ) RETURN X01Z; + + FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01; + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_UX01 ( b : BIT ) RETURN UX01; + + ------------------------------------------------------------------- + -- edge detection + ------------------------------------------------------------------- + FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN; + FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN; + + ------------------------------------------------------------------- + -- object contains an unknown + ------------------------------------------------------------------- + FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN; + FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN; + FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN; + +END std_logic_1164; diff --git a/lib/Standard/ieee/std_logic_1164_body.vhd b/lib/Standard/ieee/std_logic_1164_body.vhd new file mode 100644 index 0000000..c2ee135 --- /dev/null +++ b/lib/Standard/ieee/std_logic_1164_body.vhd @@ -0,0 +1,1384 @@ +-- -------------------------------------------------------------------- +-- +-- Title : std_logic_1164 multi-value logic system +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- Developers: IEEE model standards group (par 1164) +-- Purpose : This packages defines a standard for designers +-- : to use in describing the interconnection data types +-- : used in vhdl modeling. +-- : +-- Limitation: The logic system defined in this package may +-- : be insufficient for modeling switched transistors, +-- : since such a requirement is out of the scope of this +-- : effort. Furthermore, mathematics, primitives, +-- : timing standards, etc. are considered orthogonal +-- : issues as it relates to this package and are therefore +-- : beyond the scope of this effort. +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : std_logic_1164. The std_logic_1164 package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- -------------------------------------------------------------------- +-- modification history : +-- -------------------------------------------------------------------- +-- version | mod. date:| +-- v4.200 | 01/02/92 | +-- v4.200 | 02/26/92 | Added Synopsys Synthesis Comments +-- v4.200 | 06/01/92 | Modified the "xnor"s to be xnor functions. +-- | | (see Note bellow) +-- -------------------------------------------------------------------- +-- +-- Note: Before the VHDL'92 language being officially adopted as +-- containing the "xnor" functions, Synopsys will support +-- the xnor functions (non-overloaded). +-- +-- GongWen Huang Synopsys, Inc. +-- +-- + +-- library SYNOPSYS; +-- use SYNOPSYS.ATTRIBUTES.ALL; + + +PACKAGE std_logic_1164 IS + + ------------------------------------------------------------------- + -- logic state system (unresolved) + ------------------------------------------------------------------- + TYPE std_ulogic IS ( 'U', -- Uninitialized + 'X', -- Forcing Unknown + '0', -- Forcing 0 + '1', -- Forcing 1 + 'Z', -- High Impedance + 'W', -- Weak Unknown + 'L', -- Weak 0 + 'H', -- Weak 1 + '-' -- Don't care + ); + +-- attribute ENUM_ENCODING of std_ulogic : type is "U D 0 1 Z D 0 1 D"; + + ------------------------------------------------------------------- + -- unconstrained array of std_ulogic for use with the resolution function + ------------------------------------------------------------------- + TYPE std_ulogic_vector IS ARRAY ( NATURAL RANGE <> ) OF std_ulogic; + + ------------------------------------------------------------------- + -- resolution function + ------------------------------------------------------------------- + FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic; + --synopsys translate_off +-- attribute REFLEXIVE of resolved: function is TRUE; +-- attribute RESULT_INITIAL_VALUE of resolved: function is std_ulogic'POS('Z'); + --synopsys translate_on + + + ------------------------------------------------------------------- + -- *** industry standard logic type *** + ------------------------------------------------------------------- + SUBTYPE std_logic IS resolved std_ulogic; + + ------------------------------------------------------------------- + -- unconstrained array of std_logic for use in declaring signal arrays + ------------------------------------------------------------------- + TYPE std_logic_vector IS ARRAY ( NATURAL RANGE <>) OF std_logic; + + ------------------------------------------------------------------- + -- common subtypes + ------------------------------------------------------------------- + SUBTYPE X01 IS resolved std_ulogic RANGE 'X' TO '1'; -- ('X','0','1') + SUBTYPE X01Z IS resolved std_ulogic RANGE 'X' TO 'Z'; -- ('X','0','1','Z') + SUBTYPE UX01 IS resolved std_ulogic RANGE 'U' TO '1'; -- ('U','X','0','1') + SUBTYPE UX01Z IS resolved std_ulogic RANGE 'U' TO 'Z'; -- ('U','X','0','1','Z') + + ------------------------------------------------------------------- + -- overloaded logical operators + ------------------------------------------------------------------- + + FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01; + function "xnor" ( l : std_ulogic; r : std_ulogic ) return ux01; + FUNCTION "not" ( l : std_ulogic ) RETURN UX01; + + ------------------------------------------------------------------- + -- vectorized overloaded logical operators + ------------------------------------------------------------------- + FUNCTION "and" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "and" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "nand" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nand" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "or" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "or" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "nor" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "nor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + + FUNCTION "xor" ( l, r : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "xor" ( l, r : std_ulogic_vector ) RETURN std_ulogic_vector; + +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this std_logic_1164 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + function "xnor" ( l, r : std_logic_vector ) return std_logic_vector; + function "xnor" ( l, r : std_ulogic_vector ) return std_ulogic_vector; + FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector; + FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector; + + ------------------------------------------------------------------- + -- conversion functions + ------------------------------------------------------------------- + FUNCTION To_bit ( s : std_ulogic + --synopsys synthesis_off + ; xmap : BIT := '0' + --synopsys synthesis_on + ) RETURN BIT; + + FUNCTION To_bitvector ( s : std_logic_vector + --synopsys synthesis_off + ; xmap : BIT := '0' + --synopsys synthesis_on + ) RETURN BIT_VECTOR; + + FUNCTION To_bitvector ( s : std_ulogic_vector + --synopsys synthesis_off + ; xmap : BIT := '0' + --synopsys synthesis_on + ) RETURN BIT_VECTOR; + + FUNCTION To_StdULogic ( b : BIT ) RETURN std_ulogic; + FUNCTION To_StdLogicVector ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_StdLogicVector ( s : std_ulogic_vector ) RETURN std_logic_vector; + FUNCTION To_StdULogicVector ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_StdULogicVector ( s : std_logic_vector ) RETURN std_ulogic_vector; + + ------------------------------------------------------------------- + -- strength strippers and type convertors + ------------------------------------------------------------------- + + FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_X01 ( s : std_ulogic ) RETURN X01; + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_X01 ( b : BIT ) RETURN X01; + + FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z; + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_X01Z ( b : BIT ) RETURN X01Z; + + FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector; + FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector; + FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01; + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector; + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector; + FUNCTION To_UX01 ( b : BIT ) RETURN UX01; + + ------------------------------------------------------------------- + -- edge detection + ------------------------------------------------------------------- + --synopsys synthesis_off + FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN; + FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN; + + ------------------------------------------------------------------- + -- object contains an unknown + ------------------------------------------------------------------- + FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN; + FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN; + FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN; + --synopsys synthesis_on + +END std_logic_1164; + + +-- -------------------------------------------------------------------- +-- +-- Title : std_logic_1164 multi-value logic system +-- Library : This package shall be compiled into a library +-- : symbolically named IEEE. +-- : +-- Developers: IEEE model standards group (par 1164) +-- Purpose : This packages defines a standard for designers +-- : to use in describing the interconnection data types +-- : used in vhdl modeling. +-- : +-- Limitation: The logic system defined in this package may +-- : be insufficient for modeling switched transistors, +-- : since such a requirement is out of the scope of this +-- : effort. Furthermore, mathematics, primitives, +-- : timing standards, etc. are considered orthogonal +-- : issues as it relates to this package and are therefore +-- : beyond the scope of this effort. +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. The "package declaration" +-- : defines the types, subtypes and declarations of +-- : std_logic_1164. The std_logic_1164 package body shall be +-- : considered the formal definition of the semantics of +-- : this package. Tool developers may choose to implement +-- : the package body in the most efficient manner available +-- : to them. +-- : +-- -------------------------------------------------------------------- +-- modification history : +-- -------------------------------------------------------------------- +-- version | mod. date:| +-- v4.200 | 01/02/91 | +-- v4.200 | 02/26/92 | Added Synopsys Synthesis Comments +-- -------------------------------------------------------------------- + +PACKAGE BODY std_logic_1164 IS + ------------------------------------------------------------------- + -- local types + ------------------------------------------------------------------- + --synopsys synthesis_off + TYPE stdlogic_1d IS ARRAY (std_ulogic) OF std_ulogic; + TYPE stdlogic_table IS ARRAY(std_ulogic, std_ulogic) OF std_ulogic; + + ------------------------------------------------------------------- + -- resolution function + ------------------------------------------------------------------- + CONSTANT resolution_table : stdlogic_table := ( + -- --------------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- --------------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | + ( 'U', 'X', '0', 'X', '0', '0', '0', '0', 'X' ), -- | 0 | + ( 'U', 'X', 'X', '1', '1', '1', '1', '1', 'X' ), -- | 1 | + ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X' ), -- | Z | + ( 'U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X' ), -- | L | + ( 'U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X' ), -- | H | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - | + ); + --synopsys synthesis_on + + FUNCTION resolved ( s : std_ulogic_vector ) RETURN std_ulogic IS + -- pragma resolution_method three_state + -- pragma subpgm_id 183 + --synopsys synthesis_off + VARIABLE result : std_ulogic := 'Z'; -- weakest state default + --synopsys synthesis_on + BEGIN + -- the test for a single driver is essential otherwise the + -- loop would return 'X' for a single driver of '-' and that + -- would conflict with the value of a single driver unresolved + -- signal. + --synopsys synthesis_off + IF (s'LENGTH = 1) THEN RETURN s(s'LOW); + ELSE + FOR i IN s'RANGE LOOP + result := resolution_table(result, s(i)); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END resolved; + + ------------------------------------------------------------------- + -- tables for logical operations + ------------------------------------------------------------------- + + --synopsys synthesis_off + -- truth table for "and" function + CONSTANT and_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ), -- | U | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | X | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | 0 | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 1 | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | Z | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ), -- | W | + ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ), -- | L | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | H | + ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ) -- | - | + ); + + -- truth table for "or" function + CONSTANT or_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', '1', 'U', 'U', 'U', '1', 'U' ), -- | U | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | X | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | 1 | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | Z | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | + ( '1', '1', '1', '1', '1', '1', '1', '1', '1' ), -- | H | + ( 'U', 'X', 'X', '1', 'X', 'X', 'X', '1', 'X' ) -- | - | + ); + + -- truth table for "xor" function + CONSTANT xor_table : stdlogic_table := ( + -- ---------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- ---------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | 0 | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | 1 | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | Z | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ), -- | L | + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ), -- | H | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ) -- | - | + ); + + -- truth table for "not" function + CONSTANT not_table: stdlogic_1d := + -- ------------------------------------------------- + -- | U X 0 1 Z W L H - | + -- ------------------------------------------------- + ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' ); + --synopsys synthesis_on + + ------------------------------------------------------------------- + -- overloaded logical operators ( with optimizing hints ) + ------------------------------------------------------------------- + + FUNCTION "and" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + -- pragma built_in SYN_AND + -- pragma subpgm_id 184 + BEGIN + --synopsys synthesis_off + RETURN (and_table(l, r)); + --synopsys synthesis_on + END "and"; + + FUNCTION "nand" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + -- pragma built_in SYN_NAND + -- pragma subpgm_id 185 + BEGIN + --synopsys synthesis_off + RETURN (not_table ( and_table(l, r))); + --synopsys synthesis_on + END "nand"; + + FUNCTION "or" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + -- pragma built_in SYN_OR + -- pragma subpgm_id 186 + BEGIN + --synopsys synthesis_off + RETURN (or_table(l, r)); + --synopsys synthesis_on + END "or"; + + FUNCTION "nor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + -- pragma built_in SYN_NOR + -- pragma subpgm_id 187 + BEGIN + --synopsys synthesis_off + RETURN (not_table ( or_table( l, r ))); + --synopsys synthesis_on + END "nor"; + + FUNCTION "xor" ( l : std_ulogic; r : std_ulogic ) RETURN UX01 IS + -- pragma built_in SYN_XOR + -- pragma subpgm_id 188 + BEGIN + --synopsys synthesis_off + RETURN (xor_table(l, r)); + --synopsys synthesis_on + END "xor"; + + function "xnor" ( l : std_ulogic; r : std_ulogic ) return ux01 is + -- pragma built_in SYN_XNOR + -- pragma subpgm_id 189 + begin + --synopsys synthesis_off + return not_table(xor_table(l, r)); + --synopsys synthesis_on + end "xnor"; + +-- function xnor ( l : std_ulogic; r : std_ulogic ) return ux01 is +-- -- pragma built_in SYN_XNOR +-- -- pragma subpgm_id 189 +-- begin +-- --synopsys synthesis_off +-- return not_table(xor_table(l, r)); +-- --synopsys synthesis_on +-- end xnor; + + FUNCTION "not" ( l : std_ulogic ) RETURN UX01 IS + -- pragma built_in SYN_NOT + -- pragma subpgm_id 190 + BEGIN + --synopsys synthesis_off + RETURN (not_table(l)); + --synopsys synthesis_on + END "not"; + + ------------------------------------------------------------------- + -- and + ------------------------------------------------------------------- + FUNCTION "and" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_AND + -- pragma subpgm_id 198 + --synopsys synthesis_off + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'and' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := and_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "and"; + --------------------------------------------------------------------- + FUNCTION "and" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_AND + -- pragma subpgm_id 191 + --synopsys synthesis_off + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'and' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := and_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "and"; + ------------------------------------------------------------------- + -- nand + ------------------------------------------------------------------- + FUNCTION "nand" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_NAND + -- pragma subpgm_id 199 + --synopsys synthesis_off + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'nand' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(and_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "nand"; + --------------------------------------------------------------------- + FUNCTION "nand" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_NAND + -- pragma subpgm_id 192 + --synopsys synthesis_off + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'nand' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(and_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "nand"; + ------------------------------------------------------------------- + -- or + ------------------------------------------------------------------- + FUNCTION "or" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_OR + -- pragma subpgm_id 200 + --synopsys synthesis_off + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'or' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := or_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "or"; + --------------------------------------------------------------------- + FUNCTION "or" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_OR + -- pragma subpgm_id 193 + --synopsys synthesis_off + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'or' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := or_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "or"; + ------------------------------------------------------------------- + -- nor + ------------------------------------------------------------------- + FUNCTION "nor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_NOR + -- pragma subpgm_id 201 + --synopsys synthesis_off + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'nor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(or_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "nor"; + --------------------------------------------------------------------- + FUNCTION "nor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_NOR + -- pragma subpgm_id 194 + --synopsys synthesis_off + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'nor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := not_table(or_table (lv(i), rv(i))); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "nor"; + --------------------------------------------------------------------- + -- xor + ------------------------------------------------------------------- + FUNCTION "xor" ( l,r : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_XOR + -- pragma subpgm_id 202 + --synopsys synthesis_off + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_logic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'xor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := xor_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "xor"; + --------------------------------------------------------------------- + FUNCTION "xor" ( l,r : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_XOR + -- pragma subpgm_id 195 + --synopsys synthesis_off + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + ALIAS rv : std_ulogic_vector ( 1 TO r'LENGTH ) IS r; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + IF ( l'LENGTH /= r'LENGTH ) THEN + ASSERT FALSE + REPORT "arguments of overloaded 'xor' operator are not of the same length" + SEVERITY FAILURE; + ELSE + FOR i IN result'RANGE LOOP + result(i) := xor_table (lv(i), rv(i)); + END LOOP; + END IF; + RETURN result; + --synopsys synthesis_on + END "xor"; +-- ------------------------------------------------------------------- +-- -- xnor +-- ------------------------------------------------------------------- +-- ----------------------------------------------------------------------- +-- Note : The declaration and implementation of the "xnor" function is +-- specifically commented until at which time the VHDL language has been +-- officially adopted as containing such a function. At such a point, +-- the following comments may be removed along with this notice without +-- further "official" ballotting of this std_logic_1164 package. It is +-- the intent of this effort to provide such a function once it becomes +-- available in the VHDL standard. +-- ----------------------------------------------------------------------- + function "xnor" ( l,r : std_logic_vector ) return std_logic_vector is + -- pragma built_in SYN_XNOR + -- pragma subpgm_id 203 + --synopsys synthesis_off + alias lv : std_logic_vector ( 1 to l'length ) is l; + alias rv : std_logic_vector ( 1 to r'length ) is r; + variable result : std_logic_vector ( 1 to l'length ); + --synopsys synthesis_on + begin + --synopsys synthesis_off + if ( l'length /= r'length ) then + assert false + report "arguments of overloaded 'xnor' operator are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := not_table(xor_table (lv(i), rv(i))); + end loop; + end if; + return result; + --synopsys synthesis_on + end "xnor"; +-- --------------------------------------------------------------------- +-- function xnor ( l,r : std_ulogic_vector ) return std_ulogic_vector is +-- -- pragma built_in SYN_XNOR +-- -- pragma subpgm_id 196 +-- --synopsys synthesis_off +-- alias lv : std_ulogic_vector ( 1 to l'length ) is l; +-- alias rv : std_ulogic_vector ( 1 to r'length ) is r; +-- variable result : std_ulogic_vector ( 1 to l'length ); +-- --synopsys synthesis_on +-- begin +-- --synopsys synthesis_off +-- if ( l'length /= r'length ) then +-- assert false +-- report "arguments of overloaded 'xnor' operator are not of the same length" +-- severity failure; +-- else +-- for i in result'range loop +-- result(i) := not_table(xor_table (lv(i), rv(i))); +-- end loop; +-- end if; +-- return result; +-- --synopsys synthesis_on +-- end "xnor"; + +-- function xnor ( l,r : std_logic_vector ) return std_logic_vector is +-- -- pragma built_in SYN_XNOR +-- -- pragma subpgm_id 203 +-- --synopsys synthesis_off +-- alias lv : std_logic_vector ( 1 to l'length ) is l; +-- alias rv : std_logic_vector ( 1 to r'length ) is r; +-- variable result : std_logic_vector ( 1 to l'length ); +-- --synopsys synthesis_on +-- begin +-- --synopsys synthesis_off +-- if ( l'length /= r'length ) then +-- assert false +-- report "arguments of overloaded 'xnor' operator are not of the same length" +-- severity failure; +-- else +-- for i in result'range loop +-- result(i) := not_table(xor_table (lv(i), rv(i))); +-- end loop; +-- end if; +-- return result; +-- --synopsys synthesis_on +-- end xnor; + --------------------------------------------------------------------- + function "xnor" ( l,r : std_ulogic_vector ) return std_ulogic_vector is + -- pragma built_in SYN_XNOR + -- pragma subpgm_id 196 + --synopsys synthesis_off + alias lv : std_ulogic_vector ( 1 to l'length ) is l; + alias rv : std_ulogic_vector ( 1 to r'length ) is r; + variable result : std_ulogic_vector ( 1 to l'length ); + --synopsys synthesis_on + begin + --synopsys synthesis_off + if ( l'length /= r'length ) then + assert false + report "arguments of overloaded 'xnor' operator are not of the same length" + severity failure; + else + for i in result'range loop + result(i) := not_table(xor_table (lv(i), rv(i))); + end loop; + end if; + return result; + --synopsys synthesis_on + end "xnor"; + + + + ------------------------------------------------------------------- + -- not + ------------------------------------------------------------------- + FUNCTION "not" ( l : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_NOT + -- pragma subpgm_id 204 + --synopsys synthesis_off + ALIAS lv : std_logic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_logic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X'); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := not_table( lv(i) ); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + --------------------------------------------------------------------- + FUNCTION "not" ( l : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_NOT + -- pragma subpgm_id 197 + --synopsys synthesis_off + ALIAS lv : std_ulogic_vector ( 1 TO l'LENGTH ) IS l; + VARIABLE result : std_ulogic_vector ( 1 TO l'LENGTH ) := (OTHERS => 'X'); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := not_table( lv(i) ); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + ------------------------------------------------------------------- + -- conversion tables + ------------------------------------------------------------------- + --synopsys synthesis_off + + TYPE logic_x01_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF X01; + TYPE logic_x01z_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF X01Z; + TYPE logic_ux01_table IS ARRAY (std_ulogic'LOW TO std_ulogic'HIGH) OF UX01; + ---------------------------------------------------------- + -- table name : cvt_to_x01 + -- + -- parameters : + -- in : std_ulogic -- some logic value + -- returns : x01 -- state value of logic value + -- purpose : to convert state-strength to state only + -- + -- example : if (cvt_to_x01 (input_signal) = '1' ) then ... + -- + ---------------------------------------------------------- + CONSTANT cvt_to_x01 : logic_x01_table := ( + 'X', -- 'U' + 'X', -- 'X' + '0', -- '0' + '1', -- '1' + 'X', -- 'Z' + 'X', -- 'W' + '0', -- 'L' + '1', -- 'H' + 'X' -- '-' + ); + + ---------------------------------------------------------- + -- table name : cvt_to_x01z + -- + -- parameters : + -- in : std_ulogic -- some logic value + -- returns : x01z -- state value of logic value + -- purpose : to convert state-strength to state only + -- + -- example : if (cvt_to_x01z (input_signal) = '1' ) then ... + -- + ---------------------------------------------------------- + CONSTANT cvt_to_x01z : logic_x01z_table := ( + 'X', -- 'U' + 'X', -- 'X' + '0', -- '0' + '1', -- '1' + 'Z', -- 'Z' + 'X', -- 'W' + '0', -- 'L' + '1', -- 'H' + 'X' -- '-' + ); + + ---------------------------------------------------------- + -- table name : cvt_to_ux01 + -- + -- parameters : + -- in : std_ulogic -- some logic value + -- returns : ux01 -- state value of logic value + -- purpose : to convert state-strength to state only + -- + -- example : if (cvt_to_ux01 (input_signal) = '1' ) then ... + -- + ---------------------------------------------------------- + CONSTANT cvt_to_ux01 : logic_ux01_table := ( + 'U', -- 'U' + 'X', -- 'X' + '0', -- '0' + '1', -- '1' + 'X', -- 'Z' + 'X', -- 'W' + '0', -- 'L' + '1', -- 'H' + 'X' -- '-' + ); + --synopsys synthesis_on + + ------------------------------------------------------------------- + -- conversion functions + ------------------------------------------------------------------- + FUNCTION To_bit ( s : std_ulogic + --synopsys synthesis_off + ; xmap : BIT := '0' + --synopsys synthesis_on + ) RETURN BIT IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 205 + BEGIN + --synopsys synthesis_off + CASE s IS + WHEN '0' | 'L' => RETURN ('0'); + WHEN '1' | 'H' => RETURN ('1'); + WHEN OTHERS => RETURN xmap; + END CASE; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_bitvector ( s : std_logic_vector + --synopsys synthesis_off + ; xmap : BIT := '0' + --synopsys synthesis_on + ) RETURN BIT_VECTOR IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 206 + --synopsys synthesis_off + ALIAS sv : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; + VARIABLE result : BIT_VECTOR ( s'LENGTH-1 DOWNTO 0 ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE sv(i) IS + WHEN '0' | 'L' => result(i) := '0'; + WHEN '1' | 'H' => result(i) := '1'; + WHEN OTHERS => result(i) := xmap; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_bitvector ( s : std_ulogic_vector + --synopsys synthesis_off + ; xmap : BIT := '0' + --synopsys synthesis_on + ) RETURN BIT_VECTOR IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 207 + --synopsys synthesis_off + ALIAS sv : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; + VARIABLE result : BIT_VECTOR ( s'LENGTH-1 DOWNTO 0 ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE sv(i) IS + WHEN '0' | 'L' => result(i) := '0'; + WHEN '1' | 'H' => result(i) := '1'; + WHEN OTHERS => result(i) := xmap; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_StdULogic ( b : BIT ) RETURN std_ulogic IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 208 + BEGIN + --synopsys synthesis_off + CASE b IS + WHEN '0' => RETURN '0'; + WHEN '1' => RETURN '1'; + END CASE; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_StdLogicVector ( b : BIT_VECTOR ) RETURN std_logic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 209 + --synopsys synthesis_off + ALIAS bv : BIT_VECTOR ( b'LENGTH-1 DOWNTO 0 ) IS b; + VARIABLE result : std_logic_vector ( b'LENGTH-1 DOWNTO 0 ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_StdLogicVector ( s : std_ulogic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 210 + --synopsys synthesis_off + ALIAS sv : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; + VARIABLE result : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := sv(i); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_StdULogicVector ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 211 + --synopsys synthesis_off + ALIAS bv : BIT_VECTOR ( b'LENGTH-1 DOWNTO 0 ) IS b; + VARIABLE result : std_ulogic_vector ( b'LENGTH-1 DOWNTO 0 ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_StdULogicVector ( s : std_logic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 212 + --synopsys synthesis_off + ALIAS sv : std_logic_vector ( s'LENGTH-1 DOWNTO 0 ) IS s; + VARIABLE result : std_ulogic_vector ( s'LENGTH-1 DOWNTO 0 ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := sv(i); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + + ------------------------------------------------------------------- + -- strength strippers and type convertors + ------------------------------------------------------------------- + -- to_x01 + ------------------------------------------------------------------- + FUNCTION To_X01 ( s : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 213 + --synopsys synthesis_off + ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := cvt_to_x01 (sv(i)); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 214 + --synopsys synthesis_off + ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := cvt_to_x01 (sv(i)); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( s : std_ulogic ) RETURN X01 IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 215 + BEGIN + --synopsys synthesis_off + RETURN (cvt_to_x01(s)); + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_logic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 216 + --synopsys synthesis_off + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 217 + --synopsys synthesis_off + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01 ( b : BIT ) RETURN X01 IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 218 + BEGIN + --synopsys synthesis_off + CASE b IS + WHEN '0' => RETURN('0'); + WHEN '1' => RETURN('1'); + END CASE; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + -- to_x01z + ------------------------------------------------------------------- + FUNCTION To_X01Z ( s : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 219 + --synopsys synthesis_off + ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := cvt_to_x01z (sv(i)); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 220 + --synopsys synthesis_off + ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := cvt_to_x01z (sv(i)); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( s : std_ulogic ) RETURN X01Z IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 221 + BEGIN + --synopsys synthesis_off + RETURN (cvt_to_x01z(s)); + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_logic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 222 + --synopsys synthesis_off + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 223 + --synopsys synthesis_off + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_X01Z ( b : BIT ) RETURN X01Z IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 224 + BEGIN + --synopsys synthesis_off + CASE b IS + WHEN '0' => RETURN('0'); + WHEN '1' => RETURN('1'); + END CASE; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + -- to_ux01 + ------------------------------------------------------------------- + FUNCTION To_UX01 ( s : std_logic_vector ) RETURN std_logic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 225 + --synopsys synthesis_off + ALIAS sv : std_logic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_logic_vector ( 1 TO s'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := cvt_to_ux01 (sv(i)); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( s : std_ulogic_vector ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 226 + --synopsys synthesis_off + ALIAS sv : std_ulogic_vector ( 1 TO s'LENGTH ) IS s; + VARIABLE result : std_ulogic_vector ( 1 TO s'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + result(i) := cvt_to_ux01 (sv(i)); + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( s : std_ulogic ) RETURN UX01 IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 227 + BEGIN + --synopsys synthesis_off + RETURN (cvt_to_ux01(s)); + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_logic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 228 + --synopsys synthesis_off + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_logic_vector ( 1 TO b'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( b : BIT_VECTOR ) RETURN std_ulogic_vector IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 229 + --synopsys synthesis_off + ALIAS bv : BIT_VECTOR ( 1 TO b'LENGTH ) IS b; + VARIABLE result : std_ulogic_vector ( 1 TO b'LENGTH ); + --synopsys synthesis_on + BEGIN + --synopsys synthesis_off + FOR i IN result'RANGE LOOP + CASE bv(i) IS + WHEN '0' => result(i) := '0'; + WHEN '1' => result(i) := '1'; + END CASE; + END LOOP; + RETURN result; + --synopsys synthesis_on + END; + -------------------------------------------------------------------- + FUNCTION To_UX01 ( b : BIT ) RETURN UX01 IS + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 230 + BEGIN + --synopsys synthesis_off + CASE b IS + WHEN '0' => RETURN('0'); + WHEN '1' => RETURN('1'); + END CASE; + --synopsys synthesis_on + END; + + ------------------------------------------------------------------- + -- edge detection + ------------------------------------------------------------------- + --synopsys synthesis_off + FUNCTION rising_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS + -- pragma subpgm_id 231 + BEGIN + RETURN (s'EVENT AND (To_X01(s) = '1') AND + (To_X01(s'LAST_VALUE) = '0')); + END; + + FUNCTION falling_edge (SIGNAL s : std_ulogic) RETURN BOOLEAN IS + -- pragma subpgm_id 232 + BEGIN + RETURN (s'EVENT AND (To_X01(s) = '0') AND + (To_X01(s'LAST_VALUE) = '1')); + END; + + ------------------------------------------------------------------- + -- object contains an unknown + ------------------------------------------------------------------- + FUNCTION Is_X ( s : std_ulogic_vector ) RETURN BOOLEAN IS + -- pragma subpgm_id 233 + BEGIN + FOR i IN s'RANGE LOOP + CASE s(i) IS + WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; + WHEN OTHERS => NULL; + END CASE; + END LOOP; + RETURN FALSE; + END; + -------------------------------------------------------------------- + FUNCTION Is_X ( s : std_logic_vector ) RETURN BOOLEAN IS + -- pragma subpgm_id 234 + BEGIN + FOR i IN s'RANGE LOOP + CASE s(i) IS + WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; + WHEN OTHERS => NULL; + END CASE; + END LOOP; + RETURN FALSE; + END; + -------------------------------------------------------------------- + FUNCTION Is_X ( s : std_ulogic ) RETURN BOOLEAN IS + -- pragma subpgm_id 235 + BEGIN + CASE s IS + WHEN 'U' | 'X' | 'Z' | 'W' | '-' => RETURN TRUE; + WHEN OTHERS => NULL; + END CASE; + RETURN FALSE; + END; + --synopsys synthesis_on + +END std_logic_1164; diff --git a/lib/Standard/ieee/std_logic_arith_ex.vhd b/lib/Standard/ieee/std_logic_arith_ex.vhd new file mode 100644 index 0000000..6991f38 --- /dev/null +++ b/lib/Standard/ieee/std_logic_arith_ex.vhd @@ -0,0 +1,2088 @@ +-- -------------------------------------------------------------------- +-- +-- Title : STD_LOGIC_ARITH_EX arithmetic support for STD_ULOGIC/ +-- : STD_LOGIC_VECTOR data type +-- Library : This package shall be compiled into a logical library +-- : named IEEE. +-- Purpose : To support unsigned arithmetic operations such as +-- : addition, subtraction, multiplication etc. for std_ulogic +-- : and std_logic_vector data types. Besides it supports +-- : functions and operators for Conditional operations, +-- : shift operations, relational operation between integer +-- : and std_logic_vector types, aligning size between operands +-- : of different sizes, type conversion. +-- : It also supports a set of arithemtic, conversion, and +-- : comparison functions for SIGNED, UNSIGNED, SMALL_INT, +-- : INTEGER, STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. +-- : +-- : Modification History: TH, 24th Jan., 1994 +-- : Following functions are overloaded for STD_ULOGIC_VECTOR +-- : type: "+", "-", "*", "cond_op", "<", ">", "<=", ">=", "=", +-- : "/=", sh_left, sh_right, align_size and "to_integer" +-- : New functions added are: +-- : To_StdUlogicVector (oper: INTEGER; length: NATURAL) +-- : return STD_ULOGIC_VECTOR +-- : "+"(op1: STD_ULOGIC; op2: STD_ULOGIC) return STD_ULOGIC; +-- : "-"(op1: STD_ULOGIC; op2: STD_ULOGIC) return STD_ULOGIC; +-- +-- : Name changes from STD_LOGIC_ARITH to STD_LOGIC_ARITH +-- : operator "/" added. +-- : Vinaya: 13/9/94. +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + + +package STD_LOGIC_ARITH is + +-- ADD/SUBTRACT OPERATORS + + function "+"(op1, op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(op1: STD_LOGIC_VECTOR; op2: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(op1: STD_ULOGIC; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return STD_LOGIC_VECTOR; + + function "+"(op1, op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC_VECTOR; op2: STD_ULOGIC) return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC; op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "+"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return STD_ULOGIC_VECTOR; + function "+"(op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + + function "-"(op1, op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(op1: STD_LOGIC_VECTOR; op2: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(op1: STD_ULOGIC; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return STD_LOGIC_VECTOR; + + function "-"(op1, op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC_VECTOR; op2: STD_ULOGIC) return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC; op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "-"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return STD_ULOGIC_VECTOR; + function "-"(op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + -- UNARY OPERATORS + + function "+" (op1: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+" (op1: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + +-- MULTIPLYING OPERATORS + + function "*" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "*" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "*" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR; + function "*" (op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + function "*" (op1, op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "*" (op1: STD_ULOGIC; op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "*" (op1: STD_ULOGIC_VECTOR; op2 : STD_ULOGIC) return STD_ULOGIC_VECTOR; + +-- DIVISION OPERATORS +-- The division operators are only for internal use +-- It is not advisible to use them in design. + + function "/" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "/" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR; + function "/" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_ULOGIC; + function "/" (op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + +-- CONDITIONAL FUNCTIONS + + function cond_op (cond : boolean; left_val, right_val: STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + + function cond_op (cond : boolean; left_val, right_val: STD_ULOGIC) + return STD_ULOGIC; + + function cond_op (cond : boolean; left_val, right_val: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + +-- RELATIONAL OPERATORS + + function "<"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "<="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "/="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + + function "<"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "<"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "<="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "<="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function ">"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function ">="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "/="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "/="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + +-- SHIFT OPERATORS + + function sh_left(op1: STD_LOGIC_VECTOR; op2: NATURAL) return STD_LOGIC_VECTOR; + + function sh_right(op1: STD_LOGIC_VECTOR; op2: NATURAL) return STD_LOGIC_VECTOR; + + function sh_left(op1: STD_ULOGIC_VECTOR; op2: NATURAL) return STD_ULOGIC_VECTOR; + + function sh_right(op1: STD_ULOGIC_VECTOR; op2: NATURAL) return STD_ULOGIC_VECTOR; + + +-- FUNCTIONS TO ALLOW ASSIGNMENTS OF STD_LOGIC_VECTOR OF UNEQUAL SIZES + + + function align_size (oper : STD_LOGIC_VECTOR; size : NATURAL) return STD_LOGIC_VECTOR; + function align_size (oper : STD_ULOGIC; size : NATURAL) return STD_LOGIC_VECTOR; + + function align_size (oper : STD_ULOGIC_VECTOR; size : NATURAL) return STD_ULOGIC_VECTOR; + function align_size (oper : STD_ULOGIC; size : NATURAL) return STD_ULOGIC_VECTOR; + +-- CONVERSION TO INTEGER FROM STD_LOGIC AND STD_LOGIC_VECTOR + + function to_integer (oper : STD_LOGIC_VECTOR) return INTEGER; + function to_integer (oper: STD_ULOGIC) return INTEGER; + function to_integer (oper : STD_ULOGIC_VECTOR) return INTEGER; + + +-- CONVERSION TO STD_LOGIC_VECTOR FROM INTEGER + + function To_StdLogicVector (oper: INTEGER; length: NATURAL) return STD_LOGIC_VECTOR; + function To_StdUlogicVector (oper: INTEGER; length: NATURAL) return STD_ULOGIC_VECTOR; + +-- UTILITY FUNCTIONS + + function drive (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function drive (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function Sense (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) return STD_ULOGIC; + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + +-- CONVERSION TABLE FOR TO_INTEGER + + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + +end STD_LOGIC_ARITH; + + +package body STD_LOGIC_ARITH is + +---- IMPLEMENTATTION + +-- Functions for max size + + function max (op1,op2 : INTEGER) return INTEGER; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- ALIGN_SIZE (oper : STD_ULOGIC; size : NATURAL) return STD_LOGIC_VECTOR +-- INPUT : a std_logic value to be place in a vector and the designated +-- size of the result +-- OUTPUT: a vector of the specified size with the input value +-- truncated or aligned and padded as needed. + + function align_size (oper : STD_ULOGIC; size : NATURAL) return STD_LOGIC_VECTOR is + + variable outv : STD_LOGIC_VECTOR(size-1 downto 0) + := (others => '0'); + begin + outv(outv'RIGHT) := oper; + return (outv); + end align_size; + + +------------------------------------------------------------------------------- +--- FUNCTION : +-- ALIGN_SIZE (oper : STD_LOGIC_VECTOR; size : NATURAL) return STD_LOGIC_VECTOR +-- INPUT : a vector to be aligned and the designated size of the result +-- OUTPUT: a vector of the specified size with the input value +-- truncated or aligned and padded as needed. + function align_size (oper : STD_LOGIC_VECTOR; size : NATURAL) + return STD_LOGIC_VECTOR is + variable out_mvlv : STD_LOGIC_VECTOR(size -1 downto 0); + variable temp_oper : STD_LOGIC_VECTOR(oper'LENGTH -1 downto 0) := oper; + + begin + + -- Truncate left, right justify, pad with zeros + + if oper'length > size then -- Truncate left + out_mvlv := temp_oper(size -1 downto 0); + else + out_mvlv := (others => '0'); + out_mvlv(oper'LENGTH - 1 downto 0) := oper ; + end if; + return (out_mvlv); + end align_size; + +------------------------------------------------------------------------------- +--- FUNCTION : +-- ALIGN_SIZE (oper : STD_ULOGIC_VECTOR; size : NATURAL) return STD_ULOGIC_VECTOR +-- INPUT : a vector to be aligned and the designated size of the result +-- OUTPUT: a vector of the specified size with the input value +-- truncated or aligned and padded as needed. + function align_size (oper : STD_ULOGIC_VECTOR; size : NATURAL) + return STD_ULOGIC_VECTOR is + variable out_mvlv : STD_ULOGIC_VECTOR(size -1 downto 0); + variable temp_oper : STD_ULOGIC_VECTOR(oper'LENGTH -1 downto 0) := oper; + + begin + + -- Truncate left, right justify, pad with zeros + + if oper'length > size then -- Truncate left + out_mvlv := temp_oper(size -1 downto 0); + else + out_mvlv := (others => '0'); + out_mvlv(oper'LENGTH - 1 downto 0) := oper ; + end if; + return (out_mvlv); + end align_size; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- ALIGN_SIZE (oper : STD_ULOGIC; size : NATURAL) return STD_ULOGIC_VECTOR +-- INPUT : a std_logic value to be place in a vector and the designated +-- size of the result +-- OUTPUT: a vector of the specified size with the input value +-- truncated or aligned and padded as needed. + + function align_size (oper : STD_ULOGIC; size : NATURAL) return STD_ULOGIC_VECTOR is + + variable outv : STD_ULOGIC_VECTOR(size-1 downto 0) + := (others => '0'); + begin + outv(outv'RIGHT) := oper; + return (outv); + end align_size; + + +-------------------------------------------------------------------------------- +-- the input arrays to a given function are of different sizes. + + function max (op1, op2 : INTEGER) return INTEGER is + begin + if op1 > op2 then + return op1; + else + return op2; + end if; + end max; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- TO_STDLOGICVECTOR (oper : INTEGER; length : NATURAL) return STD_LOGIC_VECTOR +-- INPUT : An integer value +-- OUTPUT: An STD_LOGIC_VECTOR of size LENGTH representing that integer +-- value. If the length is not large enough, the value will +-- be truncated. +-------------------------------------------------------------------------------- + function To_StdLogicVector (oper: INTEGER; length: NATURAL) return STD_LOGIC_VECTOR is + variable temp : INTEGER := oper; + variable temp_result : STD_LOGIC_VECTOR (LENGTH -1 downto 0) := (others => '0'); + begin + +-- TH, 23rd May,94: PCR#521, put max neg integer check within translate on_off + +-- synergy translate_off + + if (oper = INTEGER'LEFT) then -- Max negative integer + temp_result(0) := '1'; + if (length > 31) then + temp_result(LENGTH -1 downto 31) := (others => '1'); + end if; + return temp_result; + end if; + +-- synergy translate_on + + for i in 0 to LENGTH - 1 loop + if (temp mod 2) = 1 then + temp_result(i) := '1'; + else + temp_result(i) := '0'; + end if; + exit when temp = 0; + if temp < 0 then + temp := (temp - 1) / 2; + else + temp := temp / 2; + end if; + end loop; + return temp_result; + end To_StdLogicVector; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- TO_STDULOGICVECTOR (oper : INTEGER; length : NATURAL) return STD_ULOGIC_VECTOR +-- INPUT : An integer value +-- OUTPUT: An STD_ULOGIC_VECTOR of size LENGTH representing that integer +-- value. If the length is not large enough, the value will +-- be truncated. +-------------------------------------------------------------------------------- + function To_StdULogicVector (oper: INTEGER; length: NATURAL) return STD_ULOGIC_VECTOR is + variable temp : INTEGER := oper; + variable temp_result : STD_ULOGIC_VECTOR (LENGTH -1 downto 0) := (others => '0'); + begin + + -- TH, 23rd May,94: PCR#521, put max neg integer check within translate on_off + + -- synergy translate_off + + if (oper = INTEGER'LEFT) then -- Max negative integer + temp_result(0) := '1'; + if (length > 31) then + temp_result(LENGTH -1 downto 31) := (others => '1'); + end if; + return temp_result; + end if; + + -- synergy translate_on + + for i in 0 to LENGTH - 1 loop + if (temp mod 2) = 1 then + temp_result(i) := '1'; + else + temp_result(i) := '0'; + end if; + exit when temp = 0; + if temp < 0 then + temp := (temp - 1) / 2; + else + temp := temp / 2; + end if; + end loop; + return temp_result; + end To_StdULogicVector; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "+" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_LOGIC_VECTOR +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_LOGIC vector +-- It uses table lookup to get sum and carry. +-- Note: return size is max of the operands size + + function "+" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size1: INTEGER := op1'LENGTH; + constant size2: INTEGER := op2'LENGTH; + constant size_op: INTEGER := max(size1, size2); + -- size_op is the width of the larger operand + variable loop_cnt : INTEGER := size_op - 1; + variable oper1, oper2 : STD_LOGIC_VECTOR(loop_cnt downto 0); + variable result : STD_LOGIC_VECTOR (loop_cnt downto 0) + := (others => 'X'); + -- size of result is size_op + variable lt, rt : std_ulogic; + variable carry : std_ulogic := '0'; + + begin + if not (Is_X(op1) or Is_X(op2)) then + if (size1 < size_op) then + oper1 := align_size(op1, size_op); -- Make both the + else + oper1 := op1; + end if; + if (size2 < size_op) then + oper2 := align_size(op2, size_op); -- operands of + else -- same size + oper2 := op2; + end if; + + for I in 0 to loop_cnt loop + lt := oper1(I); + rt := oper2(I); + result(I) := lt xor rt xor carry; -- sum + carry := (lt and rt) or (lt and carry) or (rt and carry); -- carry + end loop; + end if; + return (result); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC/STD_LOGIC_VECTOR +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_LOGIC vector +-- +-- Note: return size is max of the operands size + + function "+" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size_op: INTEGER := op2'length; + -- size_op is the width of the larger operand + variable oper1 : STD_LOGIC_VECTOR (size_op - 1 downto 0); + -- alligned operand to be kept in oper1 + + begin + oper1 := align_size(op1, size_op); + return (oper1 + op2); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_LOGIC_VECTOR/STD_ULOGIC +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_ULOGIC vector +-- +-- Note: return size is max of the operands size + + function "+" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR is + + constant size_op: INTEGER := op1'length; + -- size_op is the width of the larger operand + variable oper2 : STD_LOGIC_VECTOR (size_op - 1 downto 0); + -- alligned operand to be kept in oper1 + + begin + oper2 := align_size(op2, size_op); + return (op1 + oper2); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1: INTEGER; op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type INTEGER/STD_LOGIC_VECTOR +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_LOGIC vector +-- +-- Note : Return size is SIZE of op2 + + function "+"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size_op: INTEGER := op2'length; + variable result : STD_LOGIC_VECTOR(size_op - 1 downto 0); + -- retuen size is size of op2 + begin + result := To_StdLogicVector(op1, size_op) + op2; + return(result); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1: STD_LOGIC_VECTOR; op2 : INTEGER) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_LOGIC_VECTOR/INTEGER +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_LOGIC vector +-- +-- Note : Return size is SIZE of op1 + + function "+"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return STD_LOGIC_VECTOR is + + constant size_op: INTEGER := op1'length; + variable result: STD_LOGIC_VECTOR(size_op - 1 downto 0); + + begin + result := op1 + To_StdLogicVector(op2, size_op); + return(result); + end "+"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "+" (op1, op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC_VECTOR +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_LOGIC vector +-- It uses table lookup to get sum and carry. +-- Note: return size is max of the operands size + + function "+" (op1, op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + + constant size1: INTEGER := op1'LENGTH; + constant size2: INTEGER := op2'LENGTH; + constant size_op: INTEGER := max(size1, size2); + -- size_op is the width of the larger operand + variable loop_cnt : INTEGER := size_op - 1; + variable oper1, oper2 : STD_ULOGIC_VECTOR(loop_cnt downto 0); + variable result : STD_ULOGIC_VECTOR (loop_cnt downto 0) + := (others => 'X'); + -- size of result is size_op + variable lt, rt : std_ulogic; + variable carry : std_ulogic := '0'; + + begin + if not (Is_X(op1) or Is_X(op2)) then + if (size1 < size_op) then + oper1 := align_size(op1, size_op); -- Make both the + else + oper1 := op1; + end if; + if (size2 < size_op) then + oper2 := align_size(op2, size_op); -- operands of + else -- same size + oper2 := op2; + end if; + + for I in 0 to loop_cnt loop + lt := oper1(I); + rt := oper2(I); + result(I) := lt xor rt xor carry; -- sum + carry := (lt and rt) or (lt and carry) or (rt and carry); -- carry + end loop; + end if; + return (result); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1: STD_ULOGIC; op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC/STD_ULOGIC_VECTOR +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_LOGIC vector +-- +-- Note: return size is max of the operands size + + function "+" (op1: STD_ULOGIC; op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + + constant size_op: INTEGER := op2'length; + -- size_op is the width of the larger operand + variable oper1 : STD_ULOGIC_VECTOR (size_op - 1 downto 0); + -- alligned operand to be kept in oper1 + + begin + oper1 := align_size(op1, size_op); + return (oper1 + op2); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1: STD_ULOGIC_VECTOR; op2 : STD_ULOGIC) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC_VECTOR/STD_ULOGIC +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_ULOGIC vector +-- +-- Note: return size is max of the operands size + + function "+" (op1: STD_ULOGIC_VECTOR; op2 : STD_ULOGIC) return STD_ULOGIC_VECTOR is + + constant size_op: INTEGER := op1'length; + -- size_op is the width of the larger operand + variable oper2 : STD_ULOGIC_VECTOR (size_op - 1 downto 0); + -- alligned operand to be kept in oper1 + + begin + oper2 := align_size(op2, size_op); + return (op1 + oper2); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1: INTEGER; op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type INTEGER/STD_ULOGIC_VECTOR +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_LOGIC vector +-- +-- Note : Return size is SIZE of op2 + + function "+"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + + constant size_op: INTEGER := op2'length; + variable result : STD_ULOGIC_VECTOR(size_op - 1 downto 0); + -- retuen size is size of op2 + begin + result := To_StdULogicVector(op1, size_op) + op2; + return(result); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1: STD_ULOGIC_VECTOR; op2 : INTEGER) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC_VECTOR/INTEGER +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_LOGIC vector +-- +-- Note : Return size is SIZE of op1 + + function "+"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return STD_ULOGIC_VECTOR is + + constant size_op: INTEGER := op1'length; + variable result: STD_ULOGIC_VECTOR(size_op - 1 downto 0); + + begin + result := op1 + To_StdULogicVector(op2, size_op); + return(result); + end "+"; + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "+" (op1, op2: STD_ULOGIC) return STD_ULOGIC +-- INPUT : op1 and op2 of type STD_ULOGIC +-- OUTPUT : The sum of the two parameters. +-- +-- This function adds the two parameters and returns a STD_ULOGIC +-- +-- Note : Return size is SIZE of op1 + + function "+"(op1, op2: STD_ULOGIC) return STD_ULOGIC is + + begin + return(op1 xor op2); + end "+"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_LOGIC_VECTOR +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_LOGIC_VECTOR +-- It uses TWO's COMPLEMENT addition for subtraction and uses table lookup +-- to get sum and carry. + + function "-"(op1, op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size1: NATURAL := op1'LENGTH; + constant size2: NATURAL := op2'LENGTH; + constant size_op: NATURAL := max(size1, size2); + -- size_op is the width of the larger operand + variable loop_cnt : NATURAL := size_op - 1; + variable oper1, oper2 : STD_LOGIC_VECTOR(loop_cnt downto 0); + variable result : STD_LOGIC_VECTOR (loop_cnt downto 0) + := (others => 'X'); + -- size of result is size_op + variable lt, rt: STD_ULOGIC; + variable carry: STD_ULOGIC := '1'; -- initialized to '1' + -- for 2's complement of op2 + begin + if not (Is_X(op1) or Is_X(op2)) then -- operands do not have 'X' + if (size1 < size_op) then + oper1 := align_size(op1, size_op); -- Make both the same size + else + oper1 := op1; + end if; + if (size2 < size_op) then + oper2 := align_size(op2, size_op); -- operands of + else -- same size + oper2 := op2; + end if; + oper2 := not oper2; -- 1's complement of op2, extra variable + + for I in 0 to loop_cnt loop + lt := oper1(I); + rt := oper2(I); + result(I) := lt xor rt xor carry; + carry := (lt and rt) or (lt and carry) or (rt and carry); + end loop; + end if; + return (result); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 of type STD_ULOGIC and op2 of type STD_LOGIC_VECTOR +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_LOGIC_VECTOR +-- It uses TWO's COMPLEMENT addition for subtraction and uses table lookup +-- to get sum and carry. + + function "-"(op1: STD_ULOGIC; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size_op: NATURAL := op2'length; + -- size_op is the width of the larger operand + variable oper1: STD_LOGIC_VECTOR(size_op -1 downto 0); + begin + oper1 := align_size(op1, size_op); + return (oper1 - op2); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR +-- INPUT : op1 of type STD_LOGIC_VECTOR and op2 of type STD_ULOGIC +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_LOGIC_VECTOR +-- It uses TWO's COMPLEMENT addition for subtraction and uses table lookup +-- to get sum and carry. + + function "-"(op1: STD_LOGIC_VECTOR; op2: STD_ULOGIC) return STD_LOGIC_VECTOR + is + + constant size_op: NATURAL := op1'length; + -- size_op is the width of the larger operand + variable oper2: STD_LOGIC_VECTOR(size_op -1 downto 0); + begin + oper2 := align_size(op2, size_op); + return (op1 - oper2); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1: INTEGER; op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 of type INTEGER and op2 of type STD_LOGIC_VECTOR +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_LOGIC_VECTOR +-- +-- Note: Return size is SIZE of op2 + +function "-"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size_op: NATURAL := op2'length; + variable result: STD_LOGIC_VECTOR(size_op - 1 downto 0); + begin + result := To_StdLogicVector(op1, size_op) - op2; + return (result); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1: STD_LOGIC_VECTOR; op2 : INTEGER) return STD_LOGIC_VECTOR +-- INPUT : op1 of type STD_LOGIC_VECTOR and op2 of type INTEGER +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_LOGIC_VECTOR +-- +-- Note: Return size is SIZE of op1 + +function "-"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return STD_LOGIC_VECTOR is + + constant size_op: NATURAL := op1'length; + variable result: STD_LOGIC_VECTOR(size_op - 1 downto 0); + begin + result := op1 - To_StdLogicVector(op2, size_op); + return (result); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1, op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC_VECTOR +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_ULOGIC_VECTOR +-- It uses TWO's COMPLEMENT addition for subtraction and uses table lookup +-- to get sum and carry. + + function "-"(op1, op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + + constant size1: NATURAL := op1'LENGTH; + constant size2: NATURAL := op2'LENGTH; + constant size_op: NATURAL := max(size1, size2); + -- size_op is the width of the larger operand + variable loop_cnt : NATURAL := size_op - 1; + variable oper1, oper2 : STD_ULOGIC_VECTOR(loop_cnt downto 0); + variable result : STD_ULOGIC_VECTOR (loop_cnt downto 0) + := (others => 'X'); + -- size of result is size_op + variable lt, rt: STD_ULOGIC; + variable carry: STD_ULOGIC := '1'; -- initialized to '1' + -- for 2's complement of op2 + begin + if not (Is_X(op1) or Is_X(op2)) then -- operands do not have 'X' + if (size1 < size_op) then + oper1 := align_size(op1, size_op); -- Make both the same size + else + oper1 := op1; + end if; + if (size2 < size_op) then + oper2 := align_size(op2, size_op); -- operands of + else -- same size + oper2 := op2; + end if; + oper2 := not oper2; -- 1's complement of op2, extra variable + + for I in 0 to loop_cnt loop + lt := oper1(I); + rt := oper2(I); + result(I) := lt xor rt xor carry; + carry := (lt and rt) or (lt and carry) or (rt and carry); + end loop; + end if; + return (result); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1: STD_ULOGIC; op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : op1 of type STD_ULOGIC and op2 of type STD_ULOGIC_VECTOR +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_ULOGIC_VECTOR +-- It uses TWO's COMPLEMENT addition for subtraction and uses table lookup +-- to get sum and carry. + + function "-"(op1: STD_ULOGIC; op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + + constant size_op: NATURAL := op2'length; + -- size_op is the width of the larger operand + variable oper1: STD_ULOGIC_VECTOR(size_op -1 downto 0); + begin + oper1 := align_size(op1, size_op); + return (oper1 - op2); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1: STD_ULOGIC_VECTOR; op2 : STD_ULOGIC) return STD_ULOGIC_VECTOR +-- INPUT : op1 of type STD_ULOGIC_VECTOR and op2 of type STD_ULOGIC +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_ULOGIC_VECTOR +-- It uses TWO's COMPLEMENT addition for subtraction and uses table lookup +-- to get sum and carry. + + function "-"(op1: STD_ULOGIC_VECTOR; op2: STD_ULOGIC) return STD_ULOGIC_VECTOR + is + + constant size_op: NATURAL := op1'length; + -- size_op is the width of the larger operand + variable oper2: STD_ULOGIC_VECTOR(size_op -1 downto 0); + begin + oper2 := align_size(op2, size_op); + return (op1 - oper2); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1: INTEGER; op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : op1 of type INTEGER and op2 of type STD_ULOGIC_VECTOR +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_ULOGIC_VECTOR +-- +-- Note: Return size is SIZE of op2 + +function "-"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + + constant size_op: NATURAL := op2'length; + variable result: STD_ULOGIC_VECTOR(size_op - 1 downto 0); + begin + result := To_StdULogicVector(op1, size_op) - op2; + return (result); + end "-"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "-" (op1: STD_ULOGIC_VECTOR; op2 : INTEGER) return STD_ULOGIC_VECTOR +-- INPUT : op1 of type STD_ULOGIC_VECTOR and op2 of type INTEGER +-- OUTPUT : The difference of the two operands. +-- +-- This function subtracts op2 from op1 and returns a STD_ULOGIC_VECTOR +-- +-- Note: Return size is SIZE of op1 + +function "-"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return STD_ULOGIC_VECTOR is + + constant size_op: NATURAL := op1'length; + variable result: STD_ULOGIC_VECTOR(size_op - 1 downto 0); + begin + result := op1 - To_StdULogicVector(op2, size_op); + return (result); + end "-"; + + +-------------------------------------------------------------------------------- + +-- FUNCTION : +-- "-" (op1, op2: STD_ULOGIC) return STD_ULOGIC +-- INPUT : op1 and op2 of type STD_ULOGIC +-- OUTPUT : The difference of the two parameters. +-- +-- This function subtracts op2 from op1 and returns a STD_ULOGIC +-- +-- Note : Return size is 1 + + function "-"(op1, op2: STD_ULOGIC) return STD_ULOGIC is + + begin + return(op1 xor op2); + end "-"; + +---------------------------------------------------------------------------------- +-- FUNCTION : +-- "+"(op1: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; +-- INPUT : a std_logc vector +-- OUTPUT: a std_logc vector +-- The function added to support unary "+" +function "+" (op1: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is +begin + return op1; +end "+"; + +---------------------------------------------------------------------------------- +-- FUNCTION : +-- "+"(op1: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; +-- INPUT : a std_logc vector +-- OUTPUT: a std_logc vector +-- The function added to support unary "+" +function "+" (op1: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is +begin + return op1; +end "+"; + +---------------------------------------------------------------------------------- +-- FUNCTION : +-- TO_INTEGER (oper: STD_LOGIC_VECTOR) +-- INPUT : a std_logc vector +-- OUTPUT: an INTEGER value of the oper. +-- +-- This function returns the integer value of the oper. +-- If size > 31 take only lower 31 bits +-- If in oper, there is any element of value 'X' or 'Z', then +-- value integer'LEFT will be returned. + + + function to_integer (oper : STD_LOGIC_VECTOR) return INTEGER is + variable value : INTEGER := 0; + variable temp_no : INTEGER := 1; + variable temp_oper : STD_LOGIC_VECTOR(oper'range) := oper; + variable INDEX : INTEGER := 1; + begin + assert oper'length <= 31 + report "argument is too large in TO_INTEGER, only lower 31 bits will be taken" + severity WARNING; + + if (not (Is_X(oper))) then + for I in temp_oper'reverse_range loop + case (tbl_BINARY(temp_oper(I))) is + when '1' => + value := value + temp_no; + when others => + null; + end case; + INDEX := INDEX + 1; + exit when INDEX > 31; + temp_no := temp_no + temp_no; + end loop; + else + assert FALSE report + "WARNING: Illegal value detected in the conversion of TO_INTEGER" + severity WARNING; + --value := integer'LEFT; + value := 0; + end if; + return (value); + end to_integer; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- TO_INTEGER (oper: STD_ULOGIC) return INTEGER; +-- INPUT : a std_ulogic +-- OUTPUT: an INTEGER value of the oper. +-- +-- This function returns the integer value of the oper. It is overloaded +-- in this way to make translation easier. + + function to_integer (oper : STD_ULOGIC) return INTEGER is + + begin + case (tbl_BINARY(oper)) is + when '1' => + return(1); + when '0' => + return (0); + when others => + assert FALSE report + "WARNING: Illegal value detected in the conversion of TO_INTEGER" + severity WARNING; + -- return (integer'LEFT); + return (0); + end case; + end to_integer; + +---------------------------------------------------------------------------------- +-- FUNCTION : +-- TO_INTEGER (oper: STD_ULOGIC_VECTOR) +-- INPUT : a std_ulogic_vector +-- OUTPUT: an INTEGER value of the oper. +-- +-- This function returns the integer value of the oper. +-- If size > 31 take only lower 31 bits +-- If in oper, there is any element of value 'X' or 'Z', then +-- value integer'LEFT will be returned. + + + function to_integer (oper : STD_ULOGIC_VECTOR) return INTEGER is + begin + return (to_integer(To_StdLogicVector(oper))); + end to_integer; + +------------------------------------------------------------------------------ +-- Multiplication Operator -- +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "*" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_LOGIC_VECTOR +-- OUTPUT : The product of the two parameters. +-- +-- This function multiplies the two parameters and returns a STD_LOGIC vector +-- It converts the parameters to integers and then multiplies. + + function "*" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size1: INTEGER := op1'LENGTH; + constant size2: INTEGER := op2'LENGTH; + variable multiplicand, multiplier : INTEGER; + constant size_res: INTEGER := size1 + size2; + -- size_res is the width of size1+ size2 + variable result : STD_LOGIC_VECTOR (size_res -1 downto 0):= + (others => 'X'); + -- size of result is size1 + size2 + begin + if (not (Is_X(op1) or Is_X(op2))) then + multiplicand := to_integer(op1); + multiplier := to_integer(op2); + result := (others => '0'); + if ((multiplier /= 0) and (multiplicand /= 0)) then + result := To_StdLogicVector((multiplicand * multiplier), size_res); + end if; + end if; + return (result); + end "*"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "*" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC/STD_LOGIC_VECTOR +-- OUTPUT : The product of the two parameters. +-- +-- This function multiplies the two parameters and returns a STD_LOGIC vector +-- It converts the parameters to integers and then multiplies. + + function "*" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size2: INTEGER := op2'LENGTH; + variable multiplicand, multiplier : INTEGER; + + variable result : STD_LOGIC_VECTOR (size2 -1 downto 0):= + (others => 'X'); + begin + if (not (Is_X(op1) or Is_X(op2))) then + multiplicand := to_integer(op1); + if(multiplicand /= 1) then + result := (others => '0'); + else + result := op2; + end if; + end if; + return (result); + end "*"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "*" (op1 : STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_LOGIC_VECTOR/STD_ULOGIC +-- OUTPUT : The product of the two parameters. +-- +-- This function multiplies the two parameters and returns a STD_LOGIC vector +-- It converts the parameters to integers and then multiplies. + + function "*" (op1 : STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR is + + begin + return (op2 * op1); + end "*"; + +------------------------------------------------------------------------------- +-- FUNCTION : +-- "*" (op1, op2 : STD_ULOGIC) return STD_ULOGIC +-- INPUT : op1 and op2 of type STD_ULOGIC +-- OUTPUT : The product of the two parameters. +-- +-- This function multiplies op2 by op1 and returns a STD_ULOGIC value. + + function "*" (op1, op2 : STD_ULOGIC) return STD_ULOGIC is + + begin + return (op1 and op2); + end "*"; + + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "*" (op1, op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC_VECTOR +-- OUTPUT : The product of the two parameters. +-- +-- This function multiplies the two parameters and returns a STD_LOGIC vector +-- It converts the parameters to integers and then multiplies. + + function "*" (op1, op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + + constant size1: INTEGER := op1'LENGTH; + constant size2: INTEGER := op2'LENGTH; + variable multiplicand, multiplier : INTEGER; + constant size_res: INTEGER := size1 + size2; + -- size_res is the width of size1+ size2 + variable result : STD_ULOGIC_VECTOR (size_res -1 downto 0):= + (others => 'X'); + -- size of result is size1 + size2 + begin + if (not (Is_X(op1) or Is_X(op2))) then + multiplicand := to_integer(op1); + multiplier := to_integer(op2); + result := (others => '0'); + if ((multiplier /= 0) and (multiplicand /= 0)) then + result := To_StdULogicVector((multiplicand * multiplier), size_res); + end if; + end if; + return (result); + end "*"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "*" (op1: STD_ULOGIC; op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC/STD_ULOGIC_VECTOR +-- OUTPUT : The product of the two parameters. +-- +-- This function multiplies the two parameters and returns a STD_LOGIC vector +-- It converts the parameters to integers and then multiplies. + + function "*" (op1: STD_ULOGIC; op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR is + + constant size2: INTEGER := op2'LENGTH; + variable multiplicand, multiplier : INTEGER; + + variable result : STD_ULOGIC_VECTOR (size2 -1 downto 0):= + (others => 'X'); + begin + if (not (Is_X(op1) or Is_X(op2))) then + multiplicand := to_integer(op1); + if(multiplicand /= 1) then + result := (others => '0'); + else + result := op2; + end if; + end if; + return (result); + end "*"; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- "*" (op1 : STD_ULOGIC_VECTOR; op2 : STD_ULOGIC) return STD_ULOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC_VECTOR/STD_ULOGIC +-- OUTPUT : The product of the two parameters. +-- +-- This function multiplies the two parameters and returns a STD_LOGIC vector +-- It converts the parameters to integers and then multiplies. + + function "*" (op1 : STD_ULOGIC_VECTOR; op2 : STD_ULOGIC) return STD_ULOGIC_VECTOR is + + begin + return (op2 * op1); + end "*"; + + +------------------------------------------------------------------------------ +-- DIVISION OPERATORS +-- The division operators are only for internal use +-- It is not advisible to use them in design. +----------------------------------------------------------------------------- + +-- FUNCTION : +-- "/" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_LOGIC_VECTOR +-- OUTPUT : The division of the two parameters. +-- This function coverts parameters to integer then +-- does the division. For internal use only. + + + function "/" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + + constant size1: INTEGER := op1'LENGTH; + constant size2: INTEGER := op2'LENGTH; + variable operand1, operand2 : INTEGER; + constant size_res: INTEGER := size1; + + variable result : STD_LOGIC_VECTOR (size_res -1 downto 0) := (others => 'X'); + -- size of result is size1 + begin + + if (not (Is_X(op1) or Is_X(op2))) then + + operand1 := to_integer(op1); + operand2 := to_integer(op2); + + if ( operand2 /= 0 ) then + result := To_StdLogicVector( (operand1/operand2), size_res); + else + assert FALSE report + "ERROR: Division by zero detected." + severity ERROR; + return (result); + end if; + end if; + return (result); + end "/"; + +----------------------------------------------------------- +-- FUNCTION : +-- "/" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR +-- INPUT : op1 and op2 of type STD_ULOGIC/STD_LOGIC_VECTOR +-- OUTPUT : The division of the two parameters. +-- +-- This function divides the two parameters and returns +-- STD_LOGIC_VECTOR. +-- It converts the parameters to integers and then does +-- the division. + + function "/" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) return STD_LOGIC_VECTOR is + + constant size1: INTEGER := op1'LENGTH; + variable operand2 : INTEGER; + + variable result : STD_LOGIC_VECTOR (size1 -1 downto 0):= (others => 'X'); + begin + if (not (Is_X(op1) or Is_X(op2))) then + operand2 := to_integer(op2); + if(operand2 = 1) then + result := op1; + else + assert FALSE report + "ERROR: Division by zero detected." + severity ERROR; + return (result); + end if; + end if; + return (result); + end "/"; + +---------------------------------------------------------------- +-- FUNCTION : +-- "/" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_ULOGIC +-- for internal use only + + function "/" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) return STD_ULOGIC is + variable operand2 : INTEGER; + variable result : STD_ULOGIC := 'X'; + begin + if (not (Is_X(op1) or Is_X(op2))) then + operand2 := to_integer( op2 ); + if( operand2 = 1 ) then + return ( op1 ); + else + assert FALSE report + "ERROR: Division by zero detected." + severity ERROR; + return (result); + end if; + end if; + return (result); + end "/" ; + +------------------------------------------------------------------------- +-- FUNCTION : +-- "/" (op1, op2 : STD_ULOGIC) return STD_ULOGIC +-- INPUT : op1 and op2 of type STD_ULOGIC +-- OUTPUT : The division of the two parameters. +-- +-- This function divides op1 by op2 and returns a STD_ULOGIC value. + + function "/" (op1, op2 : STD_ULOGIC) return STD_ULOGIC is + variable result : STD_ULOGIC := 'X'; + begin + if (not (Is_X(op1) or Is_X(op2))) then + if( op2 = '1' ) then + return (op1); + else + assert FALSE report + "ERROR: Division by zero detected." + severity ERROR; + return ('X'); + end if; + end if; + return (result); + end "/"; + +------------------------------------------------------------------------- + +-- FUNCTION : +-- COND_OP (cond:BOOLEAN; left_val,right_val: STD_LOGIC_VECTOR) +-- return STD_LOGIC_VECTOR +-- +-- This function behaves like the conditional operator. +-- If 'cond' has a boolean value of +-- 'TRUE' then left_val is returned, else +-- 'FALSE' then right_val is returned + + function cond_op(cond: BOOLEAN; left_val,right_val:STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR is + constant size1: INTEGER := left_val'LENGTH; + constant size2: INTEGER := right_val'LENGTH; + constant size_op: INTEGER := max(size1, size2); + variable result : STD_LOGIC_VECTOR (size_op -1 downto 0); + + begin + if (cond) then + if (size1 < size_op) then + result := align_size(left_val, size_op); + else + result := left_val; + end if; + else + if (size2 < size_op) then + result := align_size(right_val, size_op); + else + result := right_val; + end if; + end if; + + return (result); + end cond_op; + + +------------------------------------------------------------------------------ +-- FUNCTION +-- COND_OP (cond:BOOLEAN; left_val,right_val: STD_ULOGIC) return STD_ULOGIC +-- +-- This function behaves like the conditional operator. +-- If 'cond' has a boolean value of +-- 'TRUE' then left_val is returned, else +-- 'FALSE' then right_val is returned + + function cond_op(cond: BOOLEAN; left_val,right_val:STD_ULOGIC) + return STD_ULOGIC is + + begin + if (cond) then + return(left_val); + else + return(right_val); + end if; + + end cond_op; + +------------------------------------------------------------------------------ +-- FUNCTION +-- COND_OP (cond:BOOLEAN; left_val,right_val: STD_ULOGIC_VECTOR) +-- return STD_ULOGIC_VECTOR +-- +-- This function behaves like the conditional operator. +-- If 'cond' has a boolean value of +-- 'TRUE' then left_val is returned, else +-- 'FALSE' then right_val is returned + + function cond_op(cond: BOOLEAN; left_val,right_val:STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR is + constant size1: INTEGER := left_val'LENGTH; + constant size2: INTEGER := right_val'LENGTH; + constant size_op: INTEGER := max(size1, size2); + variable result : STD_ULOGIC_VECTOR (size_op -1 downto 0); + + begin + if (cond) then + if (size1 < size_op) then + result := align_size(left_val, size_op); + else + result := left_val; + end if; + else + if (size2 < size_op) then + result := align_size(right_val, size_op); + else + result := right_val; + end if; + end if; + + return (result); + end cond_op; + + + +--############################################################################-- +-- -- +-- SHIFT OPERATORS +-- -- +--############################################################################-- + +-------------------------- +-- Shift Left Operators -- +-------------------------------------------------------------------------------- +-- FUNCTION : +-- SH_LEFT (op1 : STD_LOGIC_VECTOR; op2 : NATURAL) return STD_LOGIC_VECTOR +-- +-- This function left-shifts the op1, by the number of bits specified by op2 +-- and returns the shifted result (of the same size as op1). + + function sh_left (op1 : STD_LOGIC_VECTOR; op2 : NATURAL) return STD_LOGIC_VECTOR is + constant size_op: INTEGER := op1'LENGTH; + constant left : INTEGER := op1'LEFT; + constant right : INTEGER := op1'RIGHT; + variable result: STD_LOGIC_VECTOR (size_op-1 downto 0) := (others => '0'); + begin + if (op2 = 0) then + return (op1); + end if; + + if (op2 >= size_op) then -- if more than size_op bits are + return (result); -- to be shifted, the + end if; -- result is all 0's + + if (left >= right) then -- op1 is of descending range + result(size_op-1 downto op2) := op1((left - op2) downto right); + else -- op1 is of ascending range + result(size_op-1 downto op2) := op1((left + op2) to right); + end if; + + return result; + end sh_left; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- SH_LEFT (op1 : STD_ULOGIC_VECTOR; op2 : NATURAL) return STD_ULOGIC_VECTOR +-- +-- This function left-shifts the op1, by the number of bits specified by op2 +-- and returns the shifted result (of the same size as op1). + + function sh_left (op1 : STD_ULOGIC_VECTOR; op2 : NATURAL) return STD_ULOGIC_VECTOR is + constant size_op: INTEGER := op1'LENGTH; + constant left : INTEGER := op1'LEFT; + constant right : INTEGER := op1'RIGHT; + variable result: STD_ULOGIC_VECTOR (size_op-1 downto 0) := (others => '0'); + begin + if (op2 = 0) then + return (op1); + end if; + + if (op2 >= size_op) then -- if more than size_op bits are + return (result); -- to be shifted, the + end if; -- result is all 0's + + if (left >= right) then -- op1 is of descending range + result(size_op-1 downto op2) := op1((left - op2) downto right); + else -- op1 is of ascending range + result(size_op-1 downto op2) := op1((left + op2) to right); + end if; + + return result; + end sh_left; + +-------------------------------------------------------------------------------- +--------------------------- +-- Shift Right Operators -- +-------------------------------------------------------------------------------- +-- FUNCTION : +-- SH_RIGHT (op1 : STD_LOGIC_VECTOR; op2 : NATURAL) return STD_LOGIC_VECTOR +-- +-- This function right-shifts op1, by the number of bits specified by op2 +-- and returns the shifted result (of the same size as op1). + + function sh_right (op1 : STD_LOGIC_VECTOR; op2 : NATURAL) + return STD_LOGIC_VECTOR is + constant size_op: INTEGER := op1'LENGTH; + constant left : INTEGER := op1'LEFT; + constant right : INTEGER := op1'RIGHT; + variable result: STD_LOGIC_VECTOR (size_op-1 downto 0) := (others => '0'); + begin + if (op2 = 0) then + return (op1); + end if; + + if (op2 >= size_op) then -- if more than size_op bits are + return (result); -- to be shifted, the + end if; -- result is all 0's + + if (left >= right) then -- op1 is of descending range + result((size_op-1 - op2) downto 0) + := op1(left downto (right + op2)); + else -- op1 is of ascending range + result((size_op - 1 - op2) downto 0) + := op1(left to (right - op2)); + end if; + return result; + end sh_right; + +-------------------------------------------------------------------------------- +-- FUNCTION : +-- SH_RIGHT (op1 : STD_ULOGIC_VECTOR; op2 : NATURAL) return STD_ULOGIC_VECTOR +-- +-- This function right-shifts op1, by the number of bits specified by op2 +-- and returns the shifted result (of the same size as op1). + + function sh_right (op1 : STD_ULOGIC_VECTOR; op2 : NATURAL) + return STD_ULOGIC_VECTOR is + constant size_op: INTEGER := op1'LENGTH; + constant left : INTEGER := op1'LEFT; + constant right : INTEGER := op1'RIGHT; + variable result: STD_ULOGIC_VECTOR (size_op-1 downto 0) := (others => '0'); + begin + if (op2 = 0) then + return (op1); + end if; + + if (op2 >= size_op) then -- if more than size_op bits are + return (result); -- to be shifted, the + end if; -- result is all 0's + + if (left >= right) then -- op1 is of descending range + result((size_op-1 - op2) downto 0) + := op1(left downto (right + op2)); + else -- op1 is of ascending range + result((size_op - 1 - op2) downto 0) + := op1(left to (right - op2)); + end if; + return result; + end sh_right; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "<" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_LOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 < op2 else FALSE, FALSE if logic type has X + + function "<"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 < oper2; + end if; + return(retval); + end "<"; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "<" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_LOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 < op2 else FALSE, FALSE if logic type has X + + + function "<" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 < op2; + end if; + return(retval); + end "<"; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "<" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_ULOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 < op2 else FALSE, FALSE if logic type has X + + function "<"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 < oper2; + end if; + return(retval); + end "<"; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "<" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_ULOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 < op2 else FALSE, FALSE if logic type has X + + + function "<" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 < op2; + end if; + return(retval); + end "<"; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "<=" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_LOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 <= op2 else FALSE, FALSE if logic type has X + + function "<=" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 <= oper2; + end if; + return(retval); + end "<="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "<=" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_LOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 <= op2 else FALSE, FALSE if logic type has X + + + function "<=" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 <= op2; + end if; + return(retval); + end "<="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "<=" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_ULOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 <= op2 else FALSE, FALSE if logic type has X + + function "<=" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 <= oper2; + end if; + return(retval); + end "<="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "<=" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_ULOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 <= op2 else FALSE, FALSE if logic type has X + + + function "<=" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 <= op2; + end if; + return(retval); + end "<="; + +------------------------------------------------------------------------------ + +-- FUNCTION: +-- ">" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_LOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 > op2 else FALSE, FALSE if logic type has X + + function ">" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 > oper2; + end if; + return(retval); + end ">"; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- ">" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_LOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 > op2 else FALSE, FALSE if logic type has X + + + function ">" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 > op2; + end if; + return(retval); + end ">"; + +------------------------------------------------------------------------------ + +-- FUNCTION: +-- ">" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_ULOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 > op2 else FALSE, FALSE if logic type has X + + function ">" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 > oper2; + end if; + return(retval); + end ">"; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- ">" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_ULOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 > op2 else FALSE, FALSE if logic type has X + + + function ">" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 > op2; + end if; + return(retval); + end ">"; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- ">=" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_LOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 >= op2 else FALSE, FALSE if logic type has X + + function ">=" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 >= oper2; + end if; + return(retval); + end ">="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- ">=" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_LOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 >= op2 else FALSE, FALSE if logic type has X + + + function ">=" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 >= op2; + end if; + return(retval); + end ">="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- ">=" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_ULOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 >= op2 else FALSE, FALSE if logic type has X + + function ">=" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 >= oper2; + end if; + return(retval); + end ">="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- ">=" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_ULOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 >= op2 else FALSE, FALSE if logic type has X + + + function ">=" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 >= op2; + end if; + return(retval); + end ">="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "=" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_LOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 = op2 else FALSE, FALSE if logic type has X + + function "=" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 = oper2; + end if; + return(retval); + end "="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "=" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_LOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 = op2 else FALSE, FALSE if logic type has X + + + function "=" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 = op2; + end if; + return(retval); + end "="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "=" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_ULOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 = op2 else FALSE, FALSE if logic type has X + + function "=" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 = oper2; + end if; + return(retval); + end "="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "=" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_ULOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 = op2 else FALSE, FALSE if logic type has X + + + function "=" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 = op2; + end if; + return(retval); + end "="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "/=" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_LOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 /= op2 else FALSE, FALSE if logic type has X + + function "/=" (op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 /= oper2; + end if; + return(retval); + end "/="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "/=" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_LOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 /= op2 else FALSE, FALSE if logic type has X + + + function "/=" (op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 /= op2; + end if; + return(retval); + end "/="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "/=" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN +-- INPUT : op1, op2 of type INTEGER/STD_ULOGIC_VECTOR +-- OUTPUT : BOOLEAN, TRUE if op1 /= op2 else FALSE, FALSE if logic type has X + + function "/=" (op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN is + variable oper2 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op2))) then + oper2 := to_integer(op2); + retval := op1 /= oper2; + end if; + return(retval); + end "/="; + +------------------------------------------------------------------------------ +-- FUNCTION: +-- "/=" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN +-- INPUT : op1, op2 of type STD_ULOGIC_VECTOR/INTEGER +-- OUTPUT : BOOLEAN, TRUE if op1 /= op2 else FALSE, FALSE if logic type has X + + + function "/=" (op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN is + variable oper1 : INTEGER; + variable retval : BOOLEAN := FALSE; + begin + if (not (Is_X(op1))) then + oper1 := to_integer(op1); + retval := oper1 /= op2; + end if; + return(retval); + end "/="; + +------------------------------------------------------------------------------ +-- FUNCTION +-- DRIVE (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR +-- INPUT : V of type STD_LOGIC_VECTOR +-- OUTPUT : Same as input with type STD_ULOGIC_VECTOR + +function drive (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR is + variable result : std_ulogic_vector ( V'range ); +begin + for i IN V'RANGE LOOP + result(i) := V(i); + end loop; + return result; +end drive; + +----------------------------------------------------------------------------- +-- FUNCTION +-- DRIVE (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR +-- INPUT : V of type STD_ULOGIC_VECTOR +-- OUTPUT : Same as input with type STD_LOGIC_VECTOR + +function drive (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable result : std_logic_vector ( V'range ); +begin + for i IN V'RANGE LOOP + result(i) := V(i); + end loop; + return result; +end drive; + +----------------------------------------------------------------------------- +-- FUNCTION +-- SENSE (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) return STD_ULOGIC +-- INPUT : V of type STD_ULOGIC, vZ, vU, vDC of type STD_ULOGIC +-- OUTPUT : STD_ULOGIC with same value as V but its 'Z' mapped to VZ, +-- 'U' mapped to vU and '-' mapped to vDC. + +function sense (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) return STD_ULOGIC is +begin + case V is + when 'Z' => return (vZ); + when 'U' => return (vU); + when '-' => return (vDC); + when others => return (V); + end case; +end sense; +----------------------------------------------------------------------------- +-- FUNCTION +-- SENSE (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) +-- return STD_ULOGIC_VECTOR +-- INPUT : V of type STD_ULOGIC_VECTOR, vZ, vU, vDC of type STD_ULOGIC +-- OUTPUT : STD_ULOGIC_VECTOR with same value as V but its 'Z' mapped to VZ, +-- 'U' mapped to vU and '-' mapped to vDC. + +function sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR is + variable result : STD_ULOGIC_VECTOR(V'range); +begin + for I in V'RANGE loop + case V(I) is + when 'Z' => result(I) := vZ; + when 'U' => result(I) := vU; + when '-' => result(I) := vDC; + when others => result(I) := V(I); + end case; + end loop; + return (result); +end sense; +----------------------------------------------------------------------------- +-- FUNCTION +-- SENSE (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) +-- return STD_ULOGIC_VECTOR +-- INPUT : V of type STD_ULOGIC_VECTOR, vZ, vU, vDC of type STD_ULOGIC +-- OUTPUT : STD_ULOGIC_VECTOR with same value as V but its 'Z' mapped to VZ, +-- 'U' mapped to vU and '-' mapped to vDC. + +function sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR is + variable result : STD_ULOGIC_VECTOR(V'range); +begin + for I in V'RANGE loop + case V(I) is + when 'Z' => result(I) := vZ; + when 'U' => result(I) := vU; + when '-' => result(I) := vDC; + when others => result(I) := V(I); + end case; + end loop; + return (result); +end sense; +----------------------------------------------------------------------------- + +end STD_LOGIC_ARITH; diff --git a/lib/Standard/ieee/std_logic_arith_ex.vhdl b/lib/Standard/ieee/std_logic_arith_ex.vhdl new file mode 100644 index 0000000..6a6dc2c --- /dev/null +++ b/lib/Standard/ieee/std_logic_arith_ex.vhdl @@ -0,0 +1,217 @@ +-- -------------------------------------------------------------------- +-- +-- Title : STD_LOGIC_ARITH arithmetic support for STD_ULOGIC/ +-- : STD_LOGIC_VECTOR data type +-- Library : This package shall be compiled into a logical library +-- : named IEEE. +-- Purpose : To support unsigned arithmetic operations such as +-- : addition, subtraction, multiplication etc. for std_ulogic +-- : and std_logic_vector data types. Besides it supports +-- : functions and operators for Conditional operations, +-- : shift operations, relational operation between integer +-- : and std_logic_vector types, aligning size between operands +-- : of different sizes, type conversion. +-- : It also supports a set of arithemtic, conversion, and +-- : comparison functions for SIGNED, UNSIGNED, SMALL_INT, +-- : INTEGER, STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. +-- : +-- Note : No declarations or definitions shall be included in, +-- : or excluded from this package. +-- : +-- : Modification History: TH, 24th Jan., 1994 +-- : Following functions are overloaded for STD_ULOGIC_VECTOR +-- : type: "+", "-", "*", "cond_op", "<", ">", "<=", ">=", "=", +-- : "/=", sh_left, sh_right, align_size and "to_integer" +-- : New functions added are: +-- : To_StdUlogicVector (oper: INTEGER; length: NATURAL) +-- : return STD_ULOGIC_VECTOR +-- : "+"(op1: STD_ULOGIC; op2: STD_ULOGIC) return STD_ULOGIC; +-- : "-"(op1: STD_ULOGIC; op2: STD_ULOGIC) return STD_ULOGIC; +-- +-- : Name changes from STD_LOGIC_ARITH to STD_LOGIC_ARITH +-- : operator "/" added. +-- : Vinaya: 13/9/94. +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + + +package STD_LOGIC_ARITH is + +-- ADD/SUBTRACT OPERATORS + + function "+"(op1, op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(op1: STD_LOGIC_VECTOR; op2: STD_ULOGIC) + return STD_LOGIC_VECTOR; + function "+"(op1: STD_ULOGIC; op2: STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function "+"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return STD_LOGIC_VECTOR; + + function "+"(op1, op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC_VECTOR; op2: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC; op2: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function "+"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function "+"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) + return STD_ULOGIC_VECTOR; + function "+"(op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + + function "-"(op1, op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(op1: STD_LOGIC_VECTOR; op2: STD_ULOGIC) + return STD_LOGIC_VECTOR; + function "-"(op1: STD_ULOGIC; op2: STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function "-"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return STD_LOGIC_VECTOR; + + function "-"(op1, op2: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC_VECTOR; op2: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC; op2: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function "-"(op1: INTEGER; op2: STD_ULOGIC_VECTOR)return STD_ULOGIC_VECTOR; + function "-"(op1: STD_ULOGIC_VECTOR; op2: INTEGER)return STD_ULOGIC_VECTOR; + function "-"(op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + -- UNARY OPERATORS + + function "+" (op1: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+" (op1: STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + +-- MULTIPLYING OPERATORS + + function "*" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "*" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function "*" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) + return STD_LOGIC_VECTOR; + function "*" (op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + function "*" (op1, op2 : STD_ULOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function "*" (op1: STD_ULOGIC; op2 : STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + function "*" (op1: STD_ULOGIC_VECTOR; op2 : STD_ULOGIC) + return STD_ULOGIC_VECTOR; + +-- DIVISION OPERATORS +-- The division operators are only for internal use +-- It is not advisible to use them in design. + + function "/" (op1, op2 : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "/" (op1: STD_LOGIC_VECTOR; op2 : STD_ULOGIC) + return STD_LOGIC_VECTOR; + function "/" (op1: STD_ULOGIC; op2 : STD_LOGIC_VECTOR) + return STD_ULOGIC; + function "/" (op1, op2 : STD_ULOGIC) return STD_ULOGIC; + + +-- CONDITIONAL FUNCTIONS + + function cond_op (cond : boolean; left_val, right_val: STD_LOGIC_VECTOR) + return STD_LOGIC_VECTOR; + function cond_op (cond : boolean; left_val, right_val: STD_ULOGIC) + return STD_ULOGIC; + function cond_op (cond : boolean; left_val, right_val: STD_ULOGIC_VECTOR) + return STD_ULOGIC_VECTOR; + +-- RELATIONAL OPERATORS + + function "<"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "<="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">"(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "/="(op1: INTEGER; op2: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(op1: STD_LOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + + function "<"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "<"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "<="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "<="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">"(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function ">"(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function ">="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function ">="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + + function "/="(op1: INTEGER; op2: STD_ULOGIC_VECTOR) return BOOLEAN; + function "/="(op1: STD_ULOGIC_VECTOR; op2: INTEGER) return BOOLEAN; + +-- SHIFT OPERATORS + + function sh_left(op1: STD_LOGIC_VECTOR; op2: NATURAL) + return STD_LOGIC_VECTOR; + function sh_right(op1: STD_LOGIC_VECTOR; op2: NATURAL) + return STD_LOGIC_VECTOR; + function sh_left(op1: STD_ULOGIC_VECTOR; op2: NATURAL) + return STD_ULOGIC_VECTOR; + function sh_right(op1: STD_ULOGIC_VECTOR; op2: NATURAL) + return STD_ULOGIC_VECTOR; + + +-- FUNCTIONS TO ALLOW ASSIGNMENTS OF STD_LOGIC_VECTOR OF UNEQUAL SIZES + + + function align_size (oper : STD_LOGIC_VECTOR; size : NATURAL) + return STD_LOGIC_VECTOR; + function align_size (oper : STD_ULOGIC; size : NATURAL) + return STD_LOGIC_VECTOR; + function align_size (oper : STD_ULOGIC_VECTOR; size : NATURAL) + return STD_ULOGIC_VECTOR; + function align_size (oper : STD_ULOGIC; size : NATURAL) + return STD_ULOGIC_VECTOR; + +-- CONVERSION TO INTEGER FROM STD_LOGIC AND STD_LOGIC_VECTOR + + function to_integer (oper : STD_LOGIC_VECTOR) return INTEGER; + function to_integer (oper: STD_ULOGIC) return INTEGER; + function to_integer (oper : STD_ULOGIC_VECTOR) return INTEGER; + + +-- CONVERSION TO STD_LOGIC_VECTOR FROM INTEGER + + function To_StdLogicVector (oper: INTEGER; length: NATURAL) + return STD_LOGIC_VECTOR; + function To_StdUlogicVector (oper: INTEGER; length: NATURAL) + return STD_ULOGIC_VECTOR; + +-- UTILITY FUNCTIONS + + function drive (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR; + function drive (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function Sense (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) return STD_ULOGIC; + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + +-- CONVERSION TABLE FOR TO_INTEGER + + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + +end STD_LOGIC_ARITH; + diff --git a/lib/Standard/ieee/std_logic_arith_syn.vhd b/lib/Standard/ieee/std_logic_arith_syn.vhd new file mode 100644 index 0000000..9ad8f1d --- /dev/null +++ b/lib/Standard/ieee/std_logic_arith_syn.vhd @@ -0,0 +1,2391 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 296 + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 295 + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 297 + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 298 + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 301 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length), CONV_SIGNED(R, R'length))); + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 300 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_UNSIGNED(L, L'length), CONV_UNSIGNED(R, R'length))); + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 302 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length+1), CONV_SIGNED(R, R'length))); + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 303 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length), CONV_SIGNED(R, R'length+1))); + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 236 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 237 + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 238 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 239 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 240 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 241 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 242 + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 243 + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 244 + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 245 + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 246 + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 247 + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 260 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 261 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 262 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 263 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 264 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 265 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 266 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 267 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 268 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))) ; + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 269 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 270 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 271 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 248 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 249 + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 250 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 251 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 252 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 253 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 254 + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 255 + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 256 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 257 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 258 + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 259 + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 272 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + unsigned_minus(-- pragma label minus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 273 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 274 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 275 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 276 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 277 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 278 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 279 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 280 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 281 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 282 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 283 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 284 + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + -- synopsys subpgm_id 285 + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 286 + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + -- synopsys subpgm_id 287 + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 289 + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 290 + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 292 + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 294 + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 305 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 306 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 307 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 308 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 309 + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 310 + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 311 + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 312 + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 314 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 315 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 316 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 317 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 318 + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 319 + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 320 + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 321 + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 323 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 324 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 325 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 326 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 327 + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 328 + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 329 + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 330 + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 332 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 333 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 334 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 335 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 336 + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 337 + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 338 + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 339 + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 341 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 342 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 343 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 344 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 345 + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 346 + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 347 + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 348 + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 350 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 351 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 352 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 353 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 354 + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 355 + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 356 + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 357 + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 358 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + -- synopsys subpgm_id 359 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 360 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + -- synopsys subpgm_id 361 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + -- synopsys subpgm_id 365 + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + -- synopsys subpgm_id 366 + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + -- synopsys subpgm_id 367 + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + -- synopsys subpgm_id 370 + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + -- synopsys subpgm_id 371 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 372 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 373 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 375 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + -- synopsys subpgm_id 376 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + elsif (temp > integer'low) then + temp := (temp - 1) / 2; -- simulate ASR + else + temp := temp / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 377 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 378 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 380 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + -- synopsys subpgm_id 381 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + elsif (temp > integer'low) then + temp := (temp - 1) / 2; -- simulate ASR + else + temp := temp / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 382 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 383 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 384 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 385 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 386 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/lib/Standard/ieee/std_logic_arith_syn.vhdl b/lib/Standard/ieee/std_logic_arith_syn.vhdl new file mode 100644 index 0000000..e259bc3 --- /dev/null +++ b/lib/Standard/ieee/std_logic_arith_syn.vhdl @@ -0,0 +1,192 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + diff --git a/lib/Standard/ieee/std_logic_signed.vhdl b/lib/Standard/ieee/std_logic_signed.vhdl new file mode 100644 index 0000000..938ebbc --- /dev/null +++ b/lib/Standard/ieee/std_logic_signed.vhdl @@ -0,0 +1,83 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_SIGNED -- +-- -- +-- -- +-- Date: 09/11/91 KN -- +-- 10/08/92 AMT change std_ulogic to signed std_logic -- +-- 10/28/92 AMT added signed functions, -, ABS -- +-- -- +-- Purpose: -- +-- A set of signed arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: Comparision of same length std_logic_vector is defined -- +-- in the LRM. The interpretation is for unsigned vectors -- +-- This package will "overload" that definition. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_SIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "ABS"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_SIGNED; diff --git a/lib/Standard/ieee/std_logic_signed_body.vhd b/lib/Standard/ieee/std_logic_signed_body.vhd new file mode 100644 index 0000000..27d211b --- /dev/null +++ b/lib/Standard/ieee/std_logic_signed_body.vhd @@ -0,0 +1,343 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_SIGNED -- +-- -- +-- -- +-- Date: 09/11/91 KN -- +-- 10/08/92 AMT change std_ulogic to signed std_logic -- +-- 10/28/92 AMT added signed functions, -, ABS -- +-- -- +-- Purpose: -- +-- A set of signed arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: Comparision of same length std_logic_vector is defined -- +-- in the LRM. The interpretation is for unsigned vectors -- +-- This package will "overload" that definition. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_SIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "ABS"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_SIGNED; + + + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package body STD_LOGIC_SIGNED is + + + function maximum(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := SIGNED(L) + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) + R; -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) + R; -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := SIGNED(L) - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := + SIGNED(L); -- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := - SIGNED(L); -- pragma label minus + return std_logic_vector(result); + end; + + function "ABS"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := ABS( SIGNED(L)); + return std_logic_vector(result); + end; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR ((L'length+R'length-1) downto 0); + begin + result := SIGNED(L) * SIGNED(R); -- pragma label mult + return std_logic_vector(result); + end; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := maximum(L'length, R'length); + begin + return SIGNED(L) < SIGNED(R); -- pragma label lt + end; + + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + begin + return SIGNED(L) < R; -- pragma label lt + end; + + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + begin + return L < SIGNED(R); -- pragma label lt + end; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return SIGNED(L) <= SIGNED(R); -- pragma label leq + end; + + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + begin + return SIGNED(L) <= R; -- pragma label leq + end; + + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return L <= SIGNED(R); -- pragma label leq + end; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return SIGNED(L) > SIGNED(R); -- pragma label gt + end; + + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + begin + return SIGNED(L) > R; -- pragma label gt + end; + + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return L > SIGNED(R); -- pragma label gt + end; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return SIGNED(L) >= SIGNED(R); -- pragma label geq + end; + + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + begin + return SIGNED(L) >= R; -- pragma label geq + end; + + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return L >= SIGNED(R); -- pragma label geq + end; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return SIGNED(L) = SIGNED(R); + end; + + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return SIGNED(L) = R; + end; + + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L = SIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return SIGNED(L) /= SIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return SIGNED(L) /= R; + end; + + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L /= SIGNED(R); + end; + + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHL(SIGNED(ARG),UNSIGNED(COUNT))); + end; + + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHR(SIGNED(ARG),UNSIGNED(COUNT))); + end; + + + +-- This function converts std_logic_vector to a signed integer value +-- using a conversion function in std_logic_arith + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER is + variable result : SIGNED(ARG'range); + begin + result := SIGNED(ARG); + return CONV_INTEGER(result); + end; +end STD_LOGIC_SIGNED; + + diff --git a/lib/Standard/ieee/std_logic_textio.vhdl b/lib/Standard/ieee/std_logic_textio.vhdl new file mode 100644 index 0000000..ac39248 --- /dev/null +++ b/lib/Standard/ieee/std_logic_textio.vhdl @@ -0,0 +1,73 @@ +-- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. +-- +-- This source file may be used and distributed without restriction +-- provided that this copyright statement is not removed from the file +-- and that any derivative work contains this copyright notice. +-- +-- Package name: STD_LOGIC_TEXTIO +-- +-- Purpose: This package overloads the standard TEXTIO procedures +-- READ and WRITE. +-- +-- Author: CRC, TS +-- +---------------------------------------------------------------------------- + +use STD.textio.all; +library IEEE; +use IEEE.std_logic_1164.all; + +package STD_LOGIC_TEXTIO is +--synopsys synthesis_off + -- Read and Write procedures for STD_ULOGIC and STD_ULOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD: out BOOLEAN); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out +BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Read and Write procedures for STD_LOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out +BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- + -- Read and Write procedures for Hex and Octal values. + -- The values appear in the file as a series of characters + -- between 0-F (Hex), or 0-7 (Octal) respectively. + -- + + -- Hex + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: +out BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out +BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Octal + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: +out BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out +BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + +--synopsys synthesis_on +end STD_LOGIC_TEXTIO; diff --git a/lib/Standard/ieee/std_logic_textio_body.vhd b/lib/Standard/ieee/std_logic_textio_body.vhd new file mode 100644 index 0000000..f6e4236 --- /dev/null +++ b/lib/Standard/ieee/std_logic_textio_body.vhd @@ -0,0 +1,634 @@ +---------------------------------------------------------------------------- +-- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. +-- +-- This source file may be used and distributed without restriction +-- provided that this copyright statement is not removed from the file +-- and that any derivative work contains this copyright notice. +-- +-- Package name: STD_LOGIC_TEXTIO +-- +-- Purpose: This package overloads the standard TEXTIO procedures +-- READ and WRITE. +-- +-- Author: CRC, TS +-- +---------------------------------------------------------------------------- + +use STD.textio.all; +library IEEE; +use IEEE.std_logic_1164.all; + +package STD_LOGIC_TEXTIO is +--synopsys synthesis_off + -- Read and Write procedures for STD_ULOGIC and STD_ULOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD: out BOOLEAN); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Read and Write procedures for STD_LOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- + -- Read and Write procedures for Hex and Octal values. + -- The values appear in the file as a series of characters + -- between 0-F (Hex), or 0-7 (Octal) respectively. + -- + + -- Hex + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Octal + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + +--synopsys synthesis_on +end STD_LOGIC_TEXTIO; + +package body STD_LOGIC_TEXTIO is +--synopsys synthesis_off + + -- Type and constant definitions used to map STD_ULOGIC values + -- into/from character values. + + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', ERROR); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of character; + type MVL9_indexed_by_char is array (character) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (character) of MVL9plus; + + constant MVL9_to_char: char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9: MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus: MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => ERROR); + + + -- Overloaded procedures. + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD:out BOOLEAN) is + variable c: character; + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := 'U'; + good := FALSE; + else + value := char_to_MVL9(c); + good := TRUE; + end if; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD:out BOOLEAN) is + variable m: STD_ULOGIC; + variable c: character; + variable s: string(1 to value'length-1); + variable mv: STD_ULOGIC_VECTOR(0 to value'length-1); + constant allU: STD_ULOGIC_VECTOR(0 to value'length-1) + := (others => 'U'); + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := allU; + good := FALSE; + return; + end if; + + read(l, s); + for i in 1 to value'length-1 loop + if (char_to_MVL9plus(s(i)) = ERROR) then + value := allU; + good := FALSE; + return; + end if; + end loop; + + mv(0) := char_to_MVL9(c); + for i in 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := mv; + good := TRUE; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC) is + variable c: character; + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := 'U'; + assert FALSE report "READ(STD_ULOGIC) Error: Character '" & + c & "' read, expected STD_ULOGIC literal."; + else + value := char_to_MVL9(c); + end if; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable m: STD_ULOGIC; + variable c: character; + variable s: string(1 to value'length-1); + variable mv: STD_ULOGIC_VECTOR(0 to value'length-1); + constant allU: STD_ULOGIC_VECTOR(0 to value'length-1) + := (others => 'U'); + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := allU; + assert FALSE report + "READ(STD_ULOGIC_VECTOR) Error: Character '" & + c & "' read, expected STD_ULOGIC literal."; + return; + end if; + + read(l, s); + for i in 1 to value'length-1 loop + if (char_to_MVL9plus(s(i)) = ERROR) then + value := allU; + assert FALSE report + "READ(STD_ULOGIC_VECTOR) Error: Character '" & + s(i) & "' read, expected STD_ULOGIC literal."; + return; + end if; + end loop; + + mv(0) := char_to_MVL9(c); + for i in 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := mv; + end READ; + + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + write(l, MVL9_to_char(value), justified, field); + end WRITE; + + + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable s: string(1 to value'length); + variable m: STD_ULOGIC_VECTOR(1 to value'length) := value; + begin + for i in 1 to value'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(l, s, justified, field); + end WRITE; + + -- Read and Write procedures for STD_LOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + READ(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + READ(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end READ; + + procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + WRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); + end WRITE; + + + -- + -- Hex Read and Write procedures. + -- + + -- + -- Hex, and Octal Read and Write procedures for BIT_VECTOR + -- (these procedures are not exported, they are only used + -- by the STD_ULOGIC hex/octal reads and writes below. + -- + -- + + procedure Char2QuadBits(C: Character; + RESULT: out Bit_Vector(3 downto 0); + GOOD: out Boolean; + ISSUE_ERROR: in Boolean) is + begin + case c is + when '0' => result := x"0"; good := TRUE; + when '1' => result := x"1"; good := TRUE; + when '2' => result := x"2"; good := TRUE; + when '3' => result := x"3"; good := TRUE; + when '4' => result := x"4"; good := TRUE; + when '5' => result := x"5"; good := TRUE; + when '6' => result := x"6"; good := TRUE; + when '7' => result := x"7"; good := TRUE; + when '8' => result := x"8"; good := TRUE; + when '9' => result := x"9"; good := TRUE; + when 'A' => result := x"A"; good := TRUE; + when 'B' => result := x"B"; good := TRUE; + when 'C' => result := x"C"; good := TRUE; + when 'D' => result := x"D"; good := TRUE; + when 'E' => result := x"E"; good := TRUE; + when 'F' => result := x"F"; good := TRUE; + + when 'a' => result := x"A"; good := TRUE; + when 'b' => result := x"B"; good := TRUE; + when 'c' => result := x"C"; good := TRUE; + when 'd' => result := x"D"; good := TRUE; + when 'e' => result := x"E"; good := TRUE; + when 'f' => result := x"F"; good := TRUE; + when others => + if ISSUE_ERROR then + assert FALSE report + "HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)."; + end if; + good := FALSE; + end case; + end; + + procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/4; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 4 /= 0 then + assert FALSE report + "HREAD Error: Trying to read vector " & + "with an odd (non multiple of 4) length"; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2QuadBits(c, bv(0 to 3), ok, TRUE); + if not ok then + return; + end if; + + read(L, s, ok); + if not ok then + assert FALSE + report "HREAD Error: Failed to read the STRING"; + return; + end if; + + for i in 1 to ne-1 loop + Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, TRUE); + if not ok then + return; + end if; + end loop; + value := bv; + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD: out BOOLEAN) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/4; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 4 /= 0 then + good := FALSE; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2QuadBits(c, bv(0 to 3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + + for i in 1 to ne-1 loop + Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + good := TRUE; + value := bv; + end HREAD; + + + procedure HWRITE(L:inout LINE; VALUE:in BIT_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable quad: bit_vector(0 to 3); + constant ne: integer := value'length/4; + variable bv: bit_vector(0 to value'length-1) := value; + variable s: string(1 to ne); + begin + if value'length mod 4 /= 0 then + assert FALSE report + "HWRITE Error: Trying to read vector " & + "with an odd (non multiple of 4) length"; + return; + end if; + + for i in 0 to ne-1 loop + quad := bv(4*i to 4*i+3); + case quad is + when x"0" => s(i+1) := '0'; + when x"1" => s(i+1) := '1'; + when x"2" => s(i+1) := '2'; + when x"3" => s(i+1) := '3'; + when x"4" => s(i+1) := '4'; + when x"5" => s(i+1) := '5'; + when x"6" => s(i+1) := '6'; + when x"7" => s(i+1) := '7'; + when x"8" => s(i+1) := '8'; + when x"9" => s(i+1) := '9'; + when x"A" => s(i+1) := 'A'; + when x"B" => s(i+1) := 'B'; + when x"C" => s(i+1) := 'C'; + when x"D" => s(i+1) := 'D'; + when x"E" => s(i+1) := 'E'; + when x"F" => s(i+1) := 'F'; + end case; + end loop; + write(L, s, JUSTIFIED, FIELD); + end HWRITE; + + procedure Char2TriBits(C: Character; + RESULT: out bit_vector(2 downto 0); + GOOD: out Boolean; + ISSUE_ERROR: in Boolean) is + begin + case c is + when '0' => result := o"0"; good := TRUE; + when '1' => result := o"1"; good := TRUE; + when '2' => result := o"2"; good := TRUE; + when '3' => result := o"3"; good := TRUE; + when '4' => result := o"4"; good := TRUE; + when '5' => result := o"5"; good := TRUE; + when '6' => result := o"6"; good := TRUE; + when '7' => result := o"7"; good := TRUE; + when others => + if ISSUE_ERROR then + assert FALSE report + "OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)."; + end if; + good := FALSE; + end case; + end; + + procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR) is + variable c: character; + variable ok: boolean; + constant ne: integer := value'length/3; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 3 /= 0 then + assert FALSE report + "OREAD Error: Trying to read vector " & + "with an odd (non multiple of 3) length"; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2TriBits(c, bv(0 to 2), ok, TRUE); + if not ok then + return; + end if; + + read(L, s, ok); + if not ok then + assert FALSE + report "OREAD Error: Failed to read the STRING"; + return; + end if; + + for i in 1 to ne-1 loop + Char2TriBits(s(i), bv(3*i to 3*i+2), ok, TRUE); + if not ok then + return; + end if; + end loop; + value := bv; + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD: out BOOLEAN) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/3; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 3 /= 0 then + good := FALSE; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2TriBits(c, bv(0 to 2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + + for i in 1 to ne-1 loop + Char2TriBits(s(i), bv(3*i to 3*i+2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + good := TRUE; + value := bv; + end OREAD; + + + procedure OWRITE(L:inout LINE; VALUE:in BIT_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable tri: bit_vector(0 to 2); + constant ne: integer := value'length/3; + variable bv: bit_vector(0 to value'length-1) := value; + variable s: string(1 to ne); + begin + if value'length mod 3 /= 0 then + assert FALSE report + "OWRITE Error: Trying to read vector " & + "with an odd (non multiple of 3) length"; + return; + end if; + + for i in 0 to ne-1 loop + tri := bv(3*i to 3*i+2); + case tri is + when o"0" => s(i+1) := '0'; + when o"1" => s(i+1) := '1'; + when o"2" => s(i+1) := '2'; + when o"3" => s(i+1) := '3'; + when o"4" => s(i+1) := '4'; + when o"5" => s(i+1) := '5'; + when o"6" => s(i+1) := '6'; + when o"7" => s(i+1) := '7'; + end case; + end loop; + write(L, s, JUSTIFIED, FIELD); + end OWRITE; + + -- Hex Read and Write procedures for STD_LOGIC_VECTOR + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD:out BOOLEAN) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + HREAD(L, tmp, GOOD); + VALUE := To_X01(tmp); + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + HREAD(L, tmp); + VALUE := To_X01(tmp); + end HREAD; + + procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + HWRITE(L, To_bitvector(VALUE),JUSTIFIED, FIELD); + end HWRITE; + + -- Hex Read and Write procedures for STD_LOGIC_VECTOR + + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + HREAD(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + HREAD(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end HREAD; + + procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + HWRITE(L, To_bitvector(VALUE), JUSTIFIED, FIELD); + end HWRITE; + + + -- Octal Read and Write procedures for STD_ULOGIC_VECTOR + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD:out BOOLEAN) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + OREAD(L, tmp, GOOD); + VALUE := To_X01(tmp); + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + OREAD(L, tmp); + VALUE := To_X01(tmp); + end OREAD; + + procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + OWRITE(L, To_bitvector(VALUE),JUSTIFIED, FIELD); + end OWRITE; + + -- Octal Read and Write procedures for STD_LOGIC_VECTOR + + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + OREAD(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + OREAD(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end OREAD; + + procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + OWRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); + end OWRITE; + + +--synopsys synthesis_on +end STD_LOGIC_TEXTIO; diff --git a/lib/Standard/ieee/std_logic_unsigned.vhdl b/lib/Standard/ieee/std_logic_unsigned.vhdl new file mode 100644 index 0000000..8cd5377 --- /dev/null +++ b/lib/Standard/ieee/std_logic_unsigned.vhdl @@ -0,0 +1,79 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_UNSIGNED -- +-- -- +-- -- +-- Date: 09/11/92 KN -- +-- 10/08/92 AMT -- +-- -- +-- Purpose: -- +-- A set of unsigned arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: comparision of same length discrete arrays is defined -- +-- by the LRM. This package will "overload" those -- +-- definitions -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_UNSIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_UNSIGNED; diff --git a/lib/Standard/ieee/std_logic_unsigned_body.vhd b/lib/Standard/ieee/std_logic_unsigned_body.vhd new file mode 100644 index 0000000..3e29847 --- /dev/null +++ b/lib/Standard/ieee/std_logic_unsigned_body.vhd @@ -0,0 +1,329 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_UNSIGNED -- +-- -- +-- -- +-- Date: 09/11/92 KN -- +-- 10/08/92 AMT -- +-- -- +-- Purpose: -- +-- A set of unsigned arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: comparision of same length discrete arrays is defined -- +-- by the LRM. This package will "overload" those -- +-- definitions -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_UNSIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_UNSIGNED; + + + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package body STD_LOGIC_UNSIGNED is + + + function maximum(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := UNSIGNED(L) + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) + R;-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) + R;-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := UNSIGNED(L) - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) - R; + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := + UNSIGNED(L); + return std_logic_vector(result); + end; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR ((L'length+R'length-1) downto 0); + begin + result := UNSIGNED(L) * UNSIGNED(R); -- pragma label mult + return std_logic_vector(result); + end; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := maximum(L'length, R'length); + begin + return UNSIGNED(L) < UNSIGNED(R); -- pragma label lt + end; + + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + begin + return UNSIGNED(L) < R; -- pragma label lt + end; + + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + begin + return L < UNSIGNED(R); -- pragma label lt + end; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return UNSIGNED(L) <= UNSIGNED(R); -- pragma label leq + end; + + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + begin + return UNSIGNED(L) <= R; -- pragma label leq + end; + + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return L <= UNSIGNED(R); -- pragma label leq + end; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return UNSIGNED(L) > UNSIGNED(R); -- pragma label gt + end; + + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + begin + return UNSIGNED(L) > R; -- pragma label gt + end; + + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return L > UNSIGNED(R); -- pragma label gt + end; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return UNSIGNED(L) >= UNSIGNED(R); -- pragma label geq + end; + + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + begin + return UNSIGNED(L) >= R; -- pragma label geq + end; + + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return L >= UNSIGNED(R); -- pragma label geq + end; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) = UNSIGNED(R); + end; + + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return UNSIGNED(L) = R; + end; + + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L = UNSIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) /= UNSIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return UNSIGNED(L) /= R; + end; + + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L /= UNSIGNED(R); + end; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER is + variable result : UNSIGNED(ARG'range); + begin + result := UNSIGNED(ARG); + return CONV_INTEGER(result); + end; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHL(UNSIGNED(ARG),UNSIGNED(COUNT))); + end; + + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHR(UNSIGNED(ARG),UNSIGNED(COUNT))); + end; + + +-- remove this since it is already in std_logic_arith + --function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + --variable result1 : UNSIGNED (SIZE-1 downto 0); + --variable result2 : STD_LOGIC_VECTOR (SIZE-1 downto 0); + --begin + --result1 := CONV_UNSIGNED(ARG,SIZE); + --return std_logic_vector(result1); + --end; + + +end STD_LOGIC_UNSIGNED; + + diff --git a/lib/Standard/ieee_proposed/fixed_pkg_c.vhd b/lib/Standard/ieee_proposed/fixed_pkg_c.vhd new file mode 100644 index 0000000..f866474 --- /dev/null +++ b/lib/Standard/ieee_proposed/fixed_pkg_c.vhd @@ -0,0 +1,7846 @@ +------------------------------------------------------------------------------ +-- "fixed_pkg" package contains functions for fixed point math. +-- Please see the documentation for the fixed point package. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee.numeric_std.all; +-- use ieee_proposed.fixed_pkg.all; +-- Last Modified: $Date: 2006-03-28 11:38:18-05 $ +-- RCS ID: $Id: fixed_pkg_c.vhd,v 1.9 2006-03-28 11:38:18-05 l435385 Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +-- synthesis translate_off +use std.textio.all; +-- synthesis translate_on + +package fixed_pkg is + --%%% Uncomment the Generics +-- new work.fixed_generic_pkg +-- generic map ( +-- fixed_round_style => true; -- fixed_round +-- fixed_overflow_style => true; -- fixed_saturate +-- fixed_guard_bits => 3; -- number of guard bits +-- no_warning => false -- show warnings +-- ); + --%%% REMOVE THE REST OF THIS FILE. + constant fixed_round_style : BOOLEAN := true; -- round + constant fixed_overflow_style : BOOLEAN := true; -- saturate + constant fixed_guard_bits : NATURAL := 3; -- number of guard bits + constant no_warning : BOOLEAN := false; -- issue warnings + -- Author David Bishop (dbishop@vhdl.org) + -- These 5 constants are used as defaults. + -- There is a mechanism to override them in every function + constant fixed_round : BOOLEAN := true; -- Turn on rounding routine + constant fixed_truncate : BOOLEAN := false; -- Trun off rounding routine + constant fixed_saturate : BOOLEAN := true; -- Saturate large numbers + constant fixed_wrap : BOOLEAN := false; -- Wrap large numbers + constant fixedsynth_or_real : BOOLEAN; -- differed constant + -- base Unsigned fixed point type, downto direction assumed + type ufixed is array (INTEGER range <>) of STD_LOGIC; + -- base Signed fixed point type, downto direction assumed + type sfixed is array (INTEGER range <>) of STD_LOGIC; + ----------------------------------------------------------------------------- + -- Fixed point type is defined as follows: + -- 0000000000 + -- 4321012345 + -- 4 0 -5 + -- The decimal point is assumed between the "0" and "-1" index + -- Thus "0011010000" = 6.5 and would be written as 00110.10000 + -- All types are assumed to be in the "downto" direction. + + --=========================================================================== + -- Arithmetic Operators: + --=========================================================================== + -- Modify the sign of the number, 2's complement + function "abs" (arg : sfixed) return sfixed; + function "-" (arg : sfixed)return sfixed; + + -- Convert a signed fixed to an unsigned fixed + function "abs" (arg : sfixed) return ufixed; + + -- Addition + -- ufixed(a downto b) + ufixed(c downto d) + -- = ufixed(max(a,c)+1 downto min(b,d)) + function "+" (l, r : ufixed) return ufixed; + + -- sfixed(a downto b) + sfixed(c downto d) + -- = sfixed(max(a,c)+1 downto min(b,d)) + function "+" (l, r : sfixed) return sfixed; + + -- Subtraction + -- ufixed(a downto b) - ufixed(c downto d) + -- = ufixed(max(a,c)+1 downto min(b,d)) + function "-" (l, r : ufixed) return ufixed; + + -- sfixed(a downto b) - sfixed(c downto d) + -- = sfixed(max(a,c)+1 downto min(b,d)) + function "-" (l, r : sfixed) return sfixed; + + -- Multiplication + -- ufixed(a downto b) * ufixed(c downto d) = ufixed(a+c+1 downto b+d) + function "*" (l, r : ufixed) return ufixed; + + -- sfixed(a downto b) * sfixed(c downto d) = sfixed(a+c+1 downto b+d) + function "*" (l, r : sfixed) return sfixed; + + -- Division + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) + function "/" (l, r : ufixed) return ufixed; + + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) + function "/" (l, r : sfixed) return sfixed; + + -- Remainder + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) + function "rem" (l, r : ufixed) return ufixed; + + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (min(a,c) downto min(b,d)) + function "rem" (l, r : sfixed) return sfixed; + + -- Modulo + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b, d)) + function "mod" (l, r : ufixed) return ufixed; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto min(b, d)) + function "mod" (l, r : sfixed) return sfixed; + + ---------------------------------------------------------------------------- + -- Overload routines. In these routines the "real" or "natural" (integer) + -- are converted into a fixed point number and then the operation is + -- performed. It is assumed that the array will be large enough. + -- If the input is "real" then the real number is converted into a fixed of + -- the same size as the fixed point input. If the number is an "integer" + -- then it is converted into fixed with the range (l'high downto 0). + ---------------------------------------------------------------------------- + -- ufixed(a downto b) + ufixed(a downto b) = ufixed(a+1 downto b) + function "+" (l : ufixed; r : REAL) return ufixed; + + -- ufixed(c downto d) + ufixed(c downto d) = ufixed(c+1 downto d) + function "+" (l : REAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) + ufixed(a downto 0) = ufixed(a+1 downto min(0,b)) + function "+" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto min(0,d)) + function "+" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) - ufixed(a downto b) = ufixed(a+1 downto b) + function "-" (l : ufixed; r : REAL) return ufixed; + + -- ufixed(c downto d) - ufixed(c downto d) = ufixed(c+1 downto d) + function "-" (l : REAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) - ufixed(a downto 0) = ufixed(a+1 downto min(0,b)) + function "-" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed(a downto 0) + ufixed(c downto d) = ufixed(c+1 downto min(0,d)) + function "-" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) * ufixed(a downto b) = ufixed(2a+1 downto 2b) + function "*" (l : ufixed; r : REAL) return ufixed; + + -- ufixed(c downto d) * ufixed(c downto d) = ufixed(2c+1 downto 2d) + function "*" (l : REAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) + function "*" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed (a downto b) * ufixed (a downto 0) = ufixed (2a+1 downto b) + function "*" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) + function "/" (l : ufixed; r : REAL) return ufixed; + + -- ufixed(a downto b) / ufixed(a downto b) = ufixed(a-b downto b-a-1) + function "/" (l : REAL; r : ufixed) return ufixed; + + -- ufixed(a downto b) / ufixed(a downto 0) = ufixed(a downto b-a-1) + function "/" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed(c downto 0) / ufixed(c downto d) = ufixed(c-d downto -c-1) + function "/" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) rem ufixed (a downto b) = ufixed (a downto b) + function "rem" (l : ufixed; r : REAL) return ufixed; + + -- ufixed (c downto d) rem ufixed (c downto d) = ufixed (c downto d) + function "rem" (l : REAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) rem ufixed (a downto 0) = ufixed (a downto min(b,0)) + function "rem" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed (c downto 0) rem ufixed (c downto d) = ufixed (c downto min(d,0)) + function "rem" (l : NATURAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) mod ufixed (a downto b) = ufixed (a downto b) + function "mod" (l : ufixed; r : REAL) return ufixed; + + -- ufixed (c downto d) mod ufixed (c downto d) = ufixed (c downto d) + function "mod" (l : REAL; r : ufixed) return ufixed; + + -- ufixed (a downto b) mod ufixed (a downto 0) = ufixed (a downto min(b,0)) + function "mod" (l : ufixed; r : NATURAL) return ufixed; + + -- ufixed (c downto 0) mod ufixed (c downto d) = ufixed (c downto min(d,0)) + function "mod" (l : NATURAL; r : ufixed) return ufixed; + + -- sfixed(a downto b) + sfixed(a downto b) = sfixed(a+1 downto b) + function "+" (l : sfixed; r : REAL) return sfixed; + + -- sfixed(c downto d) + sfixed(c downto d) = sfixed(c+1 downto d) + function "+" (l : REAL; r : sfixed) return sfixed; + + -- sfixed(a downto b) + sfixed(a downto 0) = sfixed(a+1 downto min(0,b)) + function "+" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed(c downto 0) + sfixed(c downto d) = sfixed(c+1 downto min(0,d)) + function "+" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed(a downto b) - sfixed(a downto b) = sfixed(a+1 downto b) + function "-" (l : sfixed; r : REAL) return sfixed; + + -- sfixed(c downto d) - sfixed(c downto d) = sfixed(c+1 downto d) + function "-" (l : REAL; r : sfixed) return sfixed; + + -- sfixed(a downto b) - sfixed(a downto 0) = sfixed(a+1 downto min(0,b)) + function "-" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed(c downto 0) - sfixed(c downto d) = sfixed(c+1 downto min(0,d)) + function "-" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed(a downto b) * sfixed(a downto b) = sfixed(2a+1 downto 2b) + function "*" (l : sfixed; r : REAL) return sfixed; + + -- sfixed(c downto d) * sfixed(c downto d) = sfixed(2c+1 downto 2d) + function "*" (l : REAL; r : sfixed) return sfixed; + + -- sfixed(a downto b) * sfixed(a downto 0) = sfixed(2a+1 downto b) + function "*" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed(c downto 0) * sfixed(c downto d) = sfixed(2c+1 downto d) + function "*" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed(a downto b) / sfixed(a downto b) = sfixed(a-b+1 downto b-a) + function "/" (l : sfixed; r : REAL) return sfixed; + + -- sfixed(c downto d) / sfixed(c downto d) = sfixed(c-d+1 downto d-c) + function "/" (l : REAL; r : sfixed) return sfixed; + + -- sfixed(a downto b) / sfixed(a downto 0) = sfixed(a+1 downto b-a) + function "/" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed(c downto 0) / sfixed(c downto d) = sfixed(c-d+1 downto -c) + function "/" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed (a downto b) rem sfixed (a downto b) = sfixed (a downto b) + function "rem" (l : sfixed; r : REAL) return sfixed; + + -- sfixed (c downto d) rem sfixed (c downto d) = sfixed (c downto d) + function "rem" (l : REAL; r : sfixed) return sfixed; + + -- sfixed (a downto b) rem sfixed (a downto 0) = sfixed (a downto min(b,0)) + function "rem" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed (c downto 0) rem sfixed (c downto d) = sfixed (c downto min(d,0)) + function "rem" (l : INTEGER; r : sfixed) return sfixed; + + -- sfixed (a downto b) mod sfixed (a downto b) = sfixed (a downto b) + function "mod" (l : sfixed; r : REAL) return sfixed; + + -- sfixed (c downto d) mod sfixed (c downto d) = sfixed (c downto d) + function "mod" (l : REAL; r : sfixed) return sfixed; + + -- sfixed (a downto b) mod sfixed (a downto 0) = sfixed (a downto min(b,0)) + function "mod" (l : sfixed; r : INTEGER) return sfixed; + + -- sfixed (c downto 0) mod sfixed (c downto d) = sfixed (c downto min(d,0)) + function "mod" (l : INTEGER; r : sfixed) return sfixed; + + -- This version of divide gives the user more control + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) + function divide ( + l, r : ufixed; + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return ufixed; + + -- This version of divide gives the user more control + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) + function divide ( + l, r : sfixed; + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return sfixed; + + -- These functions return 1/X + -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) + function reciprocal ( + arg : ufixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return ufixed; + + -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) + function reciprocal ( + arg : sfixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return sfixed; + + -- REM function + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) + function remainder ( + l, r : ufixed; + constant round_style : BOOLEAN := fixed_round_style) + return ufixed; + + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (min(a,c) downto min(b,d)) + function remainder ( + l, r : sfixed; + constant round_style : BOOLEAN := fixed_round_style) + return sfixed; + + -- mod function + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b, d)) + function modulo ( + l, r : ufixed; + constant round_style : BOOLEAN := fixed_round_style) + return ufixed; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto min(b, d)) + function modulo ( + l, r : sfixed; + constant overflow_style : BOOLEAN := fixed_overflow_style; + constant round_style : BOOLEAN := fixed_round_style) + return sfixed; + + -- Procedure for those who need an "accumulator" function. + -- add_carry (ufixed(a downto b), ufixed (c downto d)) + -- = ufixed (max(a,c) downto min(b,d)) + procedure add_carry ( + L, R : in ufixed; + c_in : in STD_ULOGIC; + result : out ufixed; + c_out : out STD_ULOGIC); + + -- add_carry (sfixed(a downto b), sfixed (c downto d)) + -- = sfixed (max(a,c) downto min(b,d)) + procedure add_carry ( + L, R : in sfixed; + c_in : in STD_ULOGIC; + result : out sfixed; + c_out : out STD_ULOGIC); + + -- Scales the result by a power of 2. Width of input = width of output with + -- the decimal point moved. + function scalb (y : ufixed; N : integer) return ufixed; + function scalb (y : ufixed; N : SIGNED) return ufixed; + function scalb (y : sfixed; N : integer) return sfixed; + function scalb (y : sfixed; N : SIGNED) return sfixed; + + function Is_Negative (arg : sfixed) return BOOLEAN; + --=========================================================================== + -- Comparison Operators + --=========================================================================== + function ">" (l, r : ufixed) return BOOLEAN; + function ">" (l, r : sfixed) return BOOLEAN; + function "<" (l, r : ufixed) return BOOLEAN; + function "<" (l, r : sfixed) return BOOLEAN; + function "<=" (l, r : ufixed) return BOOLEAN; + function "<=" (l, r : sfixed) return BOOLEAN; + function ">=" (l, r : ufixed) return BOOLEAN; + function ">=" (l, r : sfixed) return BOOLEAN; + function "=" (l, r : ufixed) return BOOLEAN; + function "=" (l, r : sfixed) return BOOLEAN; + function "/=" (l, r : ufixed) return BOOLEAN; + function "/=" (l, r : sfixed) return BOOLEAN; + --%%% Uncomment the following (new syntax) +-- function "?=" (L, R : ufixed) return BOOLEAN; +-- function "?=" (L, R : sfixed) return BOOLEAN; +-- --%%% remove the following (old syntax) + function \?=\ (L, R : ufixed) return STD_ULOGIC; + function \?=\ (L, R : sfixed) return STD_ULOGIC; + -- These need to be overloaded for sfixed and ufixed + function \?/=\ (L, R : ufixed) return STD_ULOGIC; + function \?>\ (L, R : ufixed) return STD_ULOGIC; + function \?>=\ (L, R : ufixed) return STD_ULOGIC; + function \?<\ (L, R : ufixed) return STD_ULOGIC; + function \?<=\ (L, R : ufixed) return STD_ULOGIC; + function \?/=\ (L, R : sfixed) return STD_ULOGIC; + function \?>\ (L, R : sfixed) return STD_ULOGIC; + function \?>=\ (L, R : sfixed) return STD_ULOGIC; + function \?<\ (L, R : sfixed) return STD_ULOGIC; + function \?<=\ (L, R : sfixed) return STD_ULOGIC; + -- %%% Replace with the following (new syntax) +-- function "?=" (L, R : ufixed) return STD_ULOGIC; +-- function "?/=" (L, R : ufixed) return STD_ULOGIC; +-- function "?>" (L, R : ufixed) return STD_ULOGIC; +-- function "?>=" (L, R : ufixed) return STD_ULOGIC; +-- function "?<" (L, R : ufixed) return STD_ULOGIC; +-- function "?<=" (L, R : ufixed) return STD_ULOGIC; +-- function "?=" (L, R : sfixed) return STD_ULOGIC; +-- function "?/=" (L, R : sfixed) return STD_ULOGIC; +-- function "?>" (L, R : sfixed) return STD_ULOGIC; +-- function "?>=" (L, R : sfixed) return STD_ULOGIC; +-- function "?<" (L, R : sfixed) return STD_ULOGIC; +-- function "?<=" (L, R : sfixed) return STD_ULOGIC; + + function std_match (L, R : ufixed) return BOOLEAN; + function std_match (L, R : sfixed) return BOOLEAN; + + -- Overloads the default "maximum" and "minimum" function + function maximum (l, r : ufixed) return ufixed; + function minimum (l, r : ufixed) return ufixed; + function maximum (l, r : sfixed) return sfixed; + function minimum (l, r : sfixed) return sfixed; + + ---------------------------------------------------------------------------- + -- In these compare functions a natural is converted into a + -- fixed point number of the bounds "max(l'high,0) downto 0" + ---------------------------------------------------------------------------- + function "=" (l : ufixed; r : NATURAL) return BOOLEAN; + function "/=" (l : ufixed; r : NATURAL) return BOOLEAN; + function ">=" (l : ufixed; r : NATURAL) return BOOLEAN; + function "<=" (l : ufixed; r : NATURAL) return BOOLEAN; + function ">" (l : ufixed; r : NATURAL) return BOOLEAN; + function "<" (l : ufixed; r : NATURAL) return BOOLEAN; + + function "=" (l : NATURAL; r : ufixed) return BOOLEAN; + function "/=" (l : NATURAL; r : ufixed) return BOOLEAN; + function ">=" (l : NATURAL; r : ufixed) return BOOLEAN; + function "<=" (l : NATURAL; r : ufixed) return BOOLEAN; + function ">" (l : NATURAL; r : ufixed) return BOOLEAN; + function "<" (l : NATURAL; r : ufixed) return BOOLEAN; + + ---------------------------------------------------------------------------- + -- In these compare functions a real is converted into a + -- fixed point number of the bounds "l'high+1 downto l'low" + ---------------------------------------------------------------------------- + function "=" (l : ufixed; r : REAL) return BOOLEAN; + function "/=" (l : ufixed; r : REAL) return BOOLEAN; + function ">=" (l : ufixed; r : REAL) return BOOLEAN; + function "<=" (l : ufixed; r : REAL) return BOOLEAN; + function ">" (l : ufixed; r : REAL) return BOOLEAN; + function "<" (l : ufixed; r : REAL) return BOOLEAN; + + function "=" (l : REAL; r : ufixed) return BOOLEAN; + function "/=" (l : REAL; r : ufixed) return BOOLEAN; + function ">=" (l : REAL; r : ufixed) return BOOLEAN; + function "<=" (l : REAL; r : ufixed) return BOOLEAN; + function ">" (l : REAL; r : ufixed) return BOOLEAN; + function "<" (l : REAL; r : ufixed) return BOOLEAN; + + ---------------------------------------------------------------------------- + -- In these compare functions an integer is converted into a + -- fixed point number of the bounds "max(l'high,1) downto 0" + ---------------------------------------------------------------------------- + function "=" (l : sfixed; r : INTEGER) return BOOLEAN; + function "/=" (l : sfixed; r : INTEGER) return BOOLEAN; + function ">=" (l : sfixed; r : INTEGER) return BOOLEAN; + function "<=" (l : sfixed; r : INTEGER) return BOOLEAN; + function ">" (l : sfixed; r : INTEGER) return BOOLEAN; + function "<" (l : sfixed; r : INTEGER) return BOOLEAN; + + function "=" (l : INTEGER; r : sfixed) return BOOLEAN; + function "/=" (l : INTEGER; r : sfixed) return BOOLEAN; + function ">=" (l : INTEGER; r : sfixed) return BOOLEAN; + function "<=" (l : INTEGER; r : sfixed) return BOOLEAN; + function ">" (l : INTEGER; r : sfixed) return BOOLEAN; + function "<" (l : INTEGER; r : sfixed) return BOOLEAN; + + ---------------------------------------------------------------------------- + -- In these compare functions a real is converted into a + -- fixed point number of the bounds "l'high+1 downto l'low" + ---------------------------------------------------------------------------- + function "=" (l : sfixed; r : REAL) return BOOLEAN; + function "/=" (l : sfixed; r : REAL) return BOOLEAN; + function ">=" (l : sfixed; r : REAL) return BOOLEAN; + function "<=" (l : sfixed; r : REAL) return BOOLEAN; + function ">" (l : sfixed; r : REAL) return BOOLEAN; + function "<" (l : sfixed; r : REAL) return BOOLEAN; + + function "=" (l : REAL; r : sfixed) return BOOLEAN; + function "/=" (l : REAL; r : sfixed) return BOOLEAN; + function ">=" (l : REAL; r : sfixed) return BOOLEAN; + function "<=" (l : REAL; r : sfixed) return BOOLEAN; + function ">" (l : REAL; r : sfixed) return BOOLEAN; + function "<" (l : REAL; r : sfixed) return BOOLEAN; + + --=========================================================================== + -- Shift and Rotate Functions. + -- Note that sra and sla are not the same as the BIT_VECTOR version + --=========================================================================== + function "sll" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "srl" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "rol" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "ror" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "sla" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "sra" (ARG : ufixed; COUNT : INTEGER) return ufixed; + function "sll" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "srl" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "rol" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "ror" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "sla" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function "sra" (ARG : sfixed; COUNT : INTEGER) return sfixed; + function SHIFT_LEFT (ARG : ufixed; COUNT : NATURAL) return ufixed; + function SHIFT_RIGHT (ARG : ufixed; COUNT : NATURAL) return ufixed; + function SHIFT_LEFT (ARG : sfixed; COUNT : NATURAL) return sfixed; + function SHIFT_RIGHT (ARG : sfixed; COUNT : NATURAL) return sfixed; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : ufixed) return ufixed; + function "and" (L, R : ufixed) return ufixed; + function "or" (L, R : ufixed) return ufixed; + function "nand" (L, R : ufixed) return ufixed; + function "nor" (L, R : ufixed) return ufixed; + function "xor" (L, R : ufixed) return ufixed; + function "xnor" (L, R : ufixed) return ufixed; + function "not" (L : sfixed) return sfixed; + function "and" (L, R : sfixed) return sfixed; + function "or" (L, R : sfixed) return sfixed; + function "nand" (L, R : sfixed) return sfixed; + function "nor" (L, R : sfixed) return sfixed; + function "xor" (L, R : sfixed) return sfixed; + function "xnor" (L, R : sfixed) return sfixed; + + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "and" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "or" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "or" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "nand" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "nand" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "nor" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "nor" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "xor" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "xor" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "xnor" (L : STD_ULOGIC; R : ufixed) return ufixed; + function "xnor" (L : ufixed; R : STD_ULOGIC) return ufixed; + function "and" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "and" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "or" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "or" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "nand" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "nand" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "nor" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "nor" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "xor" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "xor" (L : sfixed; R : STD_ULOGIC) return sfixed; + function "xnor" (L : STD_ULOGIC; R : sfixed) return sfixed; + function "xnor" (L : sfixed; R : STD_ULOGIC) return sfixed; + + -- Reduction operators, same as numeric_std functions + -- %%% remove 12 functions (old syntax) + function and_reduce(arg : ufixed) return STD_ULOGIC; + function nand_reduce(arg : ufixed) return STD_ULOGIC; + function or_reduce(arg : ufixed) return STD_ULOGIC; + function nor_reduce(arg : ufixed) return STD_ULOGIC; + function xor_reduce(arg : ufixed) return STD_ULOGIC; + function xnor_reduce(arg : ufixed) return STD_ULOGIC; + function and_reduce(arg : sfixed) return STD_ULOGIC; + function nand_reduce(arg : sfixed) return STD_ULOGIC; + function or_reduce(arg : sfixed) return STD_ULOGIC; + function nor_reduce(arg : sfixed) return STD_ULOGIC; + function xor_reduce(arg : sfixed) return STD_ULOGIC; + function xnor_reduce(arg : sfixed) return STD_ULOGIC; + -- %%% Uncomment the following 12 functions (new syntax) + -- function "and" ( arg : ufixed ) RETURN std_ulogic; + -- function "nand" ( arg : ufixed ) RETURN std_ulogic; + -- function "or" ( arg : ufixed ) RETURN std_ulogic; + -- function "nor" ( arg : ufixed ) RETURN std_ulogic; + -- function "xor" ( arg : ufixed ) RETURN std_ulogic; + -- function "xnor" ( arg : ufixed ) RETURN std_ulogic; + -- function "and" ( arg : sfixed ) RETURN std_ulogic; + -- function "nand" ( arg : sfixed ) RETURN std_ulogic; + -- function "or" ( arg : sfixed ) RETURN std_ulogic; + -- function "nor" ( arg : sfixed ) RETURN std_ulogic; + -- function "xor" ( arg : sfixed ) RETURN std_ulogic; + -- function "xnor" ( arg : sfixed ) RETURN std_ulogic; + + -- returns arg'low-1 if not found + function find_msb (arg : ufixed; y : STD_ULOGIC) return INTEGER; + function find_msb (arg : sfixed; y : STD_ULOGIC) return INTEGER; + + -- returns arg'high+1 if not found + function find_lsb (arg : ufixed; y : STD_ULOGIC) return INTEGER; + function find_lsb (arg : sfixed; y : STD_ULOGIC) return INTEGER; + + --=========================================================================== + -- RESIZE Functions + --=========================================================================== + -- resizes the number (larger or smaller) + -- The returned result will be ufixed (left_index downto right_index) + -- If "round_style" is true, then the result will be rounded. If the MSB + -- of the remainder is a "1" AND the LSB of the unround result is a '1' or + -- the lower bits of the remainder include a '1' then the result will be + -- increased by the smallest representable number for that type. + -- The default is "true" for round_style. + -- "overflow_style" can be "true" (saturate mode) or "false" (wrap mode). + -- In saturate mode, if the number overflows then the largest possible + -- representable number is returned. If wrap mode, then the upper bits + -- of the number are truncated. + function resize ( + arg : ufixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed; + + -- "size_res" functions create the size of the output from the length + -- of the "size_res" input. The actual value of "size_res" is not used. + function resize ( + arg : ufixed; -- input + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed; + + -- Note that in "wrap" mode the sign bit is not replicated. Thus the + -- resize of a negative number can have a positive result in wrap mode. + function resize ( + arg : sfixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + function resize ( + arg : sfixed; -- input + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + --=========================================================================== + -- Conversion Functions + --=========================================================================== + -- integer (natural) to unsigned fixed point. + -- arguments are the upper and lower bounds of the number, thus + -- ufixed (7 downto -3) <= to_ufixed (int, 7, -3); + function to_ufixed ( + arg : NATURAL; -- integer + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding + return ufixed; + + function to_ufixed ( + arg : NATURAL; -- integer + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding + return ufixed; + + -- real to unsigned fixed point + function to_ufixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return ufixed; + + function to_ufixed ( + arg : REAL; -- real + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return ufixed; + + -- unsigned to unsigned fixed point + function to_ufixed ( + arg : UNSIGNED; -- unsigned + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return ufixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return ufixed; + + -- Performs a casting. ufixed (arg'range) is returned + function to_ufixed ( + arg : UNSIGNED) -- unsigned + return ufixed; + + -- unsigned fixed point to unsigned + function to_unsigned ( + arg : ufixed; -- fixed point input + constant size : NATURAL; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return UNSIGNED; + + -- unsigned fixed point to unsigned + function to_unsigned ( + arg : ufixed; -- fixed point input + size_res : UNSIGNED; -- used for length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return UNSIGNED; + + -- unsigned fixed point to real + function to_real ( + arg : ufixed) -- fixed point input + return REAL; + + -- unsigned fixed point to integer + function to_integer ( + arg : ufixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return NATURAL; + + -- Integer to sfixed + function to_sfixed ( + arg : INTEGER; -- integer + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + function to_sfixed ( + arg : INTEGER; -- integer + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + -- Real to sfixed + function to_sfixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return sfixed; + + function to_sfixed ( + arg : REAL; -- real + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return sfixed; + + -- signed to sfixed + function to_sfixed ( + arg : SIGNED; -- signed + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + function to_sfixed ( + arg : SIGNED; -- signed + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return sfixed; + + -- signed to sfixed (output assumed to be size of signed input) + function to_sfixed ( + arg : SIGNED) -- signed + return sfixed; + + -- unsigned fixed point to signed fixed point (adds a "0" sign bit) + function add_sign ( + arg : ufixed) -- unsigned fixed point + return sfixed; + + -- signed fixed point to signed + function to_signed ( + arg : sfixed; -- fixed point input + constant size : NATURAL; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return SIGNED; + + -- signed fixed point to signed + function to_signed ( + arg : sfixed; -- fixed point input + size_res : SIGNED; -- used for length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return SIGNED; + + -- signed fixed point to real + function to_real ( + arg : sfixed) -- fixed point input + return REAL; + + -- signed fixed point to integer + function to_integer ( + arg : sfixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return INTEGER; + + -- Because of the farily complicated sizing rules in the fixed point + -- packages these functions are provided to compute the result ranges + -- Example: + -- signal uf1 : ufixed (3 downto -3); + -- signal uf2 : ufixed (4 downto -2); + -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto + -- ufixed_low (3, -3, '*', 4, -2)); + -- uf1multuf2 <= uf1 * uf2; + -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod) + function ufixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + function ufixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + function sfixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + function sfixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER; + -- Same as above, but using the "size_res" input only for their ranges: + -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto + -- ufixed_low (uf1, '*', uf2)); + -- uf1multuf2 <= uf1 * uf2; + function ufixed_high (size_res : ufixed; + operation : CHARACTER := 'X'; + size_res2 : ufixed) + return INTEGER; + function ufixed_low (size_res : ufixed; + operation : CHARACTER := 'X'; + size_res2 : ufixed) + return INTEGER; + function sfixed_high (size_res : sfixed; + operation : CHARACTER := 'X'; + size_res2 : sfixed) + return INTEGER; + function sfixed_low (size_res : sfixed; + operation : CHARACTER := 'X'; + size_res2 : sfixed) + return INTEGER; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + function saturate ( + size_res : ufixed) -- only the size of this is used + return ufixed; + + function saturate ( + size_res : sfixed) -- only the size of this is used + return sfixed; + + --=========================================================================== + -- Translation Functions + --=========================================================================== + -- Maps meta-logical values + function to_01 ( + s : ufixed; -- fixed point input + constant XMAP : STD_LOGIC := '0') -- Map x to + return ufixed; + + -- maps meta-logical values + function to_01 ( + s : sfixed; -- fixed point input + constant XMAP : STD_LOGIC := '0') -- Map x to + return sfixed; + + function Is_X (arg : ufixed) return BOOLEAN; + function Is_X (arg : sfixed) return BOOLEAN; + function to_X01 (arg : ufixed) return ufixed; + function to_X01 (arg : sfixed) return sfixed; + function to_X01Z (arg : ufixed) return ufixed; + function to_X01Z (arg : sfixed) return sfixed; + function to_UX01 (arg : ufixed) return ufixed; + function to_UX01 (arg : sfixed) return sfixed; + + -- straight vector conversion routines, needed for synthesis. + -- These functions are here so that a std_logic_vector can be + -- converted to and from sfixed and ufixed. Note that you can + -- not cast these vectors because of their negative index. + function to_slv ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [ufixed return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [ufixed return STD_LOGIC_VECTOR]; + + function to_slv ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [sfixed return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [sfixed return STD_LOGIC_VECTOR]; + + function to_sulv ( + arg : ufixed) -- fp vector + return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [ufixed return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [ufixed return STD_ULOGIC_VECTOR]; + + function to_sulv ( + arg : sfixed) -- fp vector + return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [sfixed return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [sfixed return STD_ULOGIC_VECTOR]; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : ufixed) -- for size only + return ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : sfixed) -- for size only + return sfixed; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : ufixed) -- for size only + return ufixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : sfixed) -- for size only + return sfixed; + + -- As a concession to those who use a graphical DSP environment, + -- these functions take parameters in those tools format and create + -- fixed point numbers. These functions are designed to convert from + -- a std_logic_vector to the VHDL fixed point format using the conventions + -- of these packages. In a pure VHDL environment you should use the + -- "to_ufixed" and "to_sfixed" routines. + -- Unsigned fixed point + function to_UFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return ufixed; + -- signed fixed point + function to_SFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return sfixed; + -- finding the bounds of a number. These functions can be used like this: + -- signal xxx : ufixed (7 downto -3); + -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" + -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) + -- downto UFix_low(11, 3, "+", 11, 3)); + -- Where "11" is the width of xxx (xxx'length), + -- and 3 is the lower bound (abs (xxx'low)) + -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" + function UFix_high (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + function UFix_low (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + -- Same as above but for signed fixed point. Note that the width + -- of a signed fixed point number ignores the sign bit, thus + -- width = sxxx'length-1 + function SFix_high (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + function SFix_low (width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER; + --=========================================================================== + -- string and textio Functions + --=========================================================================== +-- rtl_synthesis off +-- synthesis translate_off + -- purpose: writes fixed point into a line + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + -- purpose: writes fixed point into a line + procedure WRITE ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure READ(L : inout LINE; + VALUE : out ufixed); + + procedure READ(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN); + + procedure READ(L : inout LINE; + VALUE : out sfixed); + + procedure READ(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN); + + alias bwrite is WRITE [LINE, ufixed, SIDE, width]; + alias bwrite is WRITE [LINE, sfixed, SIDE, width]; + alias bread is READ [LINE, ufixed]; + alias bread is READ [LINE, ufixed, BOOLEAN]; + alias bread is READ [LINE, sfixed]; + alias bread is READ [LINE, sfixed, BOOLEAN]; + + -- octal read and write + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OWRITE ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure OREAD(L : inout LINE; + VALUE : out ufixed); + + procedure OREAD(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN); + + procedure OREAD(L : inout LINE; + VALUE : out sfixed); + + procedure OREAD(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN); + + -- hex read and write + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + -- purpose: writes fixed point into a line + procedure HWRITE ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0); + + procedure HREAD(L : inout LINE; + VALUE : out ufixed); + + procedure HREAD(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN); + + procedure HREAD(L : inout LINE; + VALUE : out sfixed); + + procedure HREAD(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN); + + -- returns a string, useful for: + -- assert (x = y) report "error found " & to_string(x) severity error; + function to_string ( + value : ufixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + alias to_bstring is to_string [ufixed, SIDE, width return STRING]; + + function to_ostring ( + value : ufixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + function to_hstring ( + value : ufixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + function to_string ( + value : sfixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + alias to_bstring is to_string [sfixed, SIDE, width return STRING]; + + function to_ostring ( + value : sfixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + function to_hstring ( + value : sfixed; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + -- From string functions allow you to convert a string into a fixed + -- point number. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5 + -- The "." is optional in this syntax, however it exist and is + -- in the wrong location an error is produced. Overflow will + -- result in saturation. + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + alias from_bstring is from_string [STRING, INTEGER, INTEGER return ufixed]; + + -- Octal and hex conversions work as follows: + -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped) + -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped) + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed; + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + alias from_bstring is from_string [STRING, INTEGER, INTEGER return sfixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed; + + -- Same as above, "size_res" is used for it's range only. + function from_string ( + bstring : STRING; -- binary string + size_res : ufixed) + return ufixed; + alias from_bstring is from_string [STRING, ufixed return ufixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : ufixed) + return ufixed; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : ufixed) + return ufixed; + + function from_string ( + bstring : STRING; -- binary string + size_res : sfixed) + return sfixed; + alias from_bstring is from_string [STRING, sfixed return sfixed]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : sfixed) + return sfixed; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : sfixed) + return sfixed; + + -- Direct converstion functions. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100"); -- 6.5 + -- In this case the "." is not optional, and the size of + -- the output must match exactly. + function from_string ( + bstring : STRING) -- binary string + return ufixed; + alias from_bstring is from_string [STRING return ufixed]; + + -- Direct octal and hex converstion functions. In this case + -- the string lengths must match. Example: + -- signal sf1 := sfixed (5 downto -3); + -- sf1 <= from_ostring ("71.4") -- -6.5 + function from_ostring ( + ostring : STRING) -- Octal string + return ufixed; + + function from_hstring ( + hstring : STRING) -- hex string + return ufixed; + + function from_string ( + bstring : STRING) -- binary string + return sfixed; + alias from_bstring is from_string [STRING return sfixed]; + + function from_ostring ( + ostring : STRING) -- Octal string + return sfixed; + + function from_hstring ( + hstring : STRING) -- hex string + return sfixed; + +-- synthesis translate_on +-- rtl_synthesis on + -- This type is here for the floating point package. + type round_type is (round_nearest, -- Default, nearest LSB '0' + round_inf, -- Round to positive + round_neginf, -- Round to negate + round_zero); -- Round towards zero + -- These are the same as the C FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, + -- and FE_TOWARDZERO floating point rounding macros. + function to_StdLogicVector ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR; + function to_Std_Logic_Vector ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR; + function to_StdLogicVector ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR; + function to_Std_Logic_Vector ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR; +end package fixed_pkg; +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee.math_real.all; +use std.textio.all; +use ieee.std_logic_textio.all; -- %%% for testing only +package body fixed_pkg is + -- Author David Bishop (dbishop@vhdl.org) + -- Other contributers: Jim Lewis, Yannick Grugni, Ryan W. Hilton + -- null array constants + constant NAUF : ufixed (0 downto 1) := (others => '0'); + constant NASF : sfixed (0 downto 1) := (others => '0'); + constant NSLV : STD_LOGIC_VECTOR (0 downto 1) := (others => '0'); + + -- This differed constant will tell you if the package body is synthesizable + -- or implemented as real numbers, set to "true" if synthesizable. + constant fixedsynth_or_real : BOOLEAN := true; + + --%%% Can be removed in vhdl-200x, will be implicit. + -- purpose: To find the largest of 2 numbers + function maximum (l, r : INTEGER) + return INTEGER is + begin -- function maximum + if L > R then return L; + else return R; + end if; + end function maximum; + + function minimum (l, r : INTEGER) + return INTEGER is + begin -- function minimum + if L > R then return R; + else return L; + end if; + end function minimum; + + -- %%% Remove the following function (duplicates of new numeric_std) + function "sra" (arg : SIGNED; count : INTEGER) + return SIGNED is + begin + if (COUNT >= 0) then + return SHIFT_RIGHT(arg, count); + else + return SHIFT_LEFT(arg, -count); + end if; + end function "sra"; + + -- %%% Replace or_reducex with "or", and_reducex with "and", and + -- %%% xor_reducex with "xor", then remove the following 3 functions + -- purpose: OR all of the bits in a vector together + -- This is a copy of the proposed "or_reduce" from 1076.3 + function or_reducex (arg : STD_LOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_LOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_LOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '0'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := or_reducex (BUS_int (BUS_int'left downto Half)); + Lower := or_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper or Lower; + end if; + end if; + return Result; + end function or_reducex; + + -- purpose: AND all of the bits in a vector together + -- This is a copy of the proposed "and_reduce" from 1076.3 + function and_reducex (arg : STD_LOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_LOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_LOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '1'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := and_reducex (BUS_int (BUS_int'left downto Half)); + Lower := and_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper and Lower; + end if; + end if; + return Result; + end function and_reducex; + + function xor_reducex (arg : STD_LOGIC_VECTOR) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := xor_reducex (BUS_int (BUS_int'left downto Half)); + Lower := xor_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper xor Lower; + end if; + end if; + return Result; + end function xor_reducex; + + --%%% remove the following function and table + -- Match table, copied form new std_logic_1164 + type stdlogic_table is array(STD_ULOGIC, STD_ULOGIC) of STD_ULOGIC; + constant match_logic_table : stdlogic_table := ( + ----------------------------------------------------- + -- U X 0 1 Z W L H - | | + ----------------------------------------------------- + ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '1'), -- | U | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | X | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | 0 | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | 1 | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | Z | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '1'), -- | W | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '1'), -- | L | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '1'), -- | H | + ('1', '1', '1', '1', '1', '1', '1', '1', '1') -- | - | + ); + + constant no_match_logic_table : stdlogic_table := ( + ----------------------------------------------------- + -- U X 0 1 Z W L H - | | + ----------------------------------------------------- + ('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', '0'), -- | U | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | X | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | 0 | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | 1 | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | Z | + ('U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', '0'), -- | W | + ('U', 'X', '0', '1', 'X', 'X', '0', '1', '0'), -- | L | + ('U', 'X', '1', '0', 'X', 'X', '1', '0', '0'), -- | H | + ('0', '0', '0', '0', '0', '0', '0', '0', '0') -- | - | + ); + + ------------------------------------------------------------------- + -- ?= functions, Similar to "std_match", but returns "std_ulogic". + ------------------------------------------------------------------- + -- %%% FUNCTION "?=" ( l, r : std_ulogic ) RETURN std_ulogic IS + function \?=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin + return match_logic_table (l, r); + end function \?=\; + -- %%% END FUNCTION "?="; + -- %%% FUNCTION "?/=" ( l, r : std_ulogic ) RETURN std_ulogic is + function \?/=\ (l, r : STD_ULOGIC) return STD_ULOGIC is + begin + return no_match_logic_table (l, r); + end function \?/=\; + -- %%% END FUNCTION "?/="; + -- %%% end remove + + -- Special version of "minimum" to do some boundary checking without errors + function mins (l, r : INTEGER) + return INTEGER is + begin -- function mins + if (L = INTEGER'low or R = INTEGER'low) then + return 0; -- error condition + end if; + return minimum (L, R); + end function mins; + + -- Special version of "minimum" to do some boundary checking with errors + function mine (l, r : INTEGER) + return INTEGER is + begin -- function mine + if (L = INTEGER'low or R = INTEGER'low) then + report "FIXED_GENERIC_PKG: Unbounded number passed, was a literal used?" + severity error; + return 0; + end if; + return minimum (L, R); + end function mine; + + -- The following functions are used only internally. Every function + -- calls "cleanvec" either directly or indirectly. + -- purpose: Fixes "downto" problem and resolves meta states + function cleanvec ( + arg : sfixed) -- input + return sfixed is + constant left_index : INTEGER := maximum(arg'left, arg'right); + constant right_index : INTEGER := mins(arg'left, arg'right); + variable result : sfixed (arg'range); + begin -- function cleanvec + assert not ((arg'left < arg'right) and (arg'low /= INTEGER'low)) + report "FIXED_GENERIC_PKG: Vector passed using a ""to"" range, expected is ""downto""" + severity error; + return arg; + end function cleanvec; + + -- purpose: Fixes "downto" problem and resolves meta states + function cleanvec ( + arg : ufixed) -- input + return ufixed is + constant left_index : INTEGER := maximum(arg'left, arg'right); + constant right_index : INTEGER := mins(arg'left, arg'right); + variable result : ufixed (arg'range); + begin -- function cleanvec + assert not ((arg'left < arg'right) and (arg'low /= INTEGER'low)) + report "FIXED_GENERIC_PKG: Vector passed using a ""to"" range, expected is ""downto""" + severity error; + return arg; + end function cleanvec; + + -- Type cast a "unsigned" into a "ufixed", used internally + function to_fixed ( + arg : UNSIGNED; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); +-- variable j : INTEGER := arg'high; -- index for arg + begin -- function to_fixed + result := ufixed(arg); +-- floop : for i in result'range loop +-- result(i) := arg(j); -- res(4) := arg (4 + 3) +-- j := j - 1; +-- end loop floop; + return result; + end function to_fixed; + + -- Type cast a "signed" into an "sfixed", used internally + function to_fixed ( + arg : SIGNED; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); +-- variable j : INTEGER := arg'high; -- index for arg + begin -- function to_fixed + result := sfixed(arg); +-- floop : for i in result'range loop +-- result(i) := arg(j); -- res(4) := arg (4 + 3) +-- j := j - 1; +-- end loop floop; + return result; + end function to_fixed; + + -- Type cast a "ufixed" into an "unsigned", used internally + function to_uns ( + arg : ufixed) -- fp vector + return UNSIGNED is + subtype t is UNSIGNED(arg'high - arg'low downto 0); + variable slv : t; + begin -- function to_uns + slv := t(arg); +-- floop : for i in slv'range loop +-- slv(i) := arg(i + arg'low); -- slv(7) := arg (7 - 3) +-- end loop floop; + return UNSIGNED(to_X01(std_logic_vector(slv))); + end function to_uns; + + -- Type cast an "sfixed" into a "signed", used internally + function to_s ( + arg : sfixed) -- fp vector + return SIGNED is + subtype t is SIGNED(arg'high - arg'low downto 0); + variable slv : t; + begin -- function to_s + slv := t(arg); +-- floop : for i in slv'range loop +-- slv(i) := arg(i + arg'low); -- slv(7) := arg (7 - 3) +-- end loop floop; + return SIGNED(to_X01(std_logic_vector(slv))); + end function to_s; + + -- adds 1 to the LSB of the number + procedure round_up (arg : in ufixed; + result : out ufixed; + overflowx : out BOOLEAN) is + variable arguns, resuns : UNSIGNED (arg'high-arg'low+1 downto 0) := + (others => '0'); + begin -- round_up + arguns (arguns'high-1 downto 0) := to_uns (arg); + resuns := arguns + 1; + result := to_fixed(resuns(arg'high-arg'low + downto 0), arg'high, arg'low); + overflowx := (resuns(resuns'high) = '1'); + end procedure round_up; + + -- adds 1 to the LSB of the number + procedure round_up (arg : in sfixed; + result : out sfixed; + overflowx : out BOOLEAN) is + variable args, ress : SIGNED (arg'high-arg'low+1 downto 0); + begin -- round_up + args (args'high-1 downto 0) := to_s (arg); + args(args'high) := arg(arg'high); -- sign extend + ress := args + 1; + result := to_fixed(ress (ress'high-1 + downto 0), arg'high, arg'low); + overflowx := ((arg(arg'high) /= ress(ress'high-1)) + and (or_reducex (STD_LOGIC_VECTOR(ress)) /= '0')); + end procedure round_up; + + -- Rounding - Performs a "round_nearest" (IEEE 754) which rounds up + -- when the remainder is > 0.5. If the remainder IS 0.5 then if the + -- bottom bit is a "1" it is rounded, otherwise it remains the same. + function round_fixed (arg : ufixed; + remainder : ufixed; + overflow_style : BOOLEAN := fixed_overflow_style) + return ufixed is + variable rounds : BOOLEAN; + variable round_overflow : BOOLEAN; + variable result : ufixed (arg'range); + begin + rounds := false; + if (remainder'length > 1) then + if (remainder (remainder'high) = '1') then + rounds := (arg(arg'low) = '1') + or (or_reducex (to_slv(remainder(remainder'high-1 downto + remainder'low))) = '1'); + end if; + else + rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); + end if; + if rounds then + round_up(arg => arg, + result => result, + overflowx => round_overflow); + else + result := arg; + end if; + if (overflow_style = fixed_saturate) and round_overflow then + result := saturate (result'high, result'low); + end if; + return result; + end function round_fixed; + + -- Rounding case statement + function round_fixed (arg : sfixed; + remainder : sfixed; + overflow_style : BOOLEAN := fixed_overflow_style) + return sfixed is + variable rounds : BOOLEAN; + variable round_overflow : BOOLEAN; + variable result : sfixed (arg'range); + begin + rounds := false; + if (remainder'length > 1) then + if (remainder (remainder'high) = '1') then + rounds := (arg(arg'low) = '1') + or (or_reducex (to_slv(remainder(remainder'high-1 downto + remainder'low))) = '1'); + end if; + else + rounds := (arg(arg'low) = '1') and (remainder (remainder'high) = '1'); + end if; + if rounds then + round_up(arg => arg, + result => result, + overflowx => round_overflow); + else + result := arg; + end if; + if round_overflow then + if (overflow_style = fixed_saturate) then + if arg(arg'high) = '0' then + result := saturate (result'high, result'low); + else + result := not saturate (result'high, result'low); + end if; +-- else +-- result(result'high) := arg(arg'high); -- fix sign bit in wrap + end if; + end if; + return result; + end function round_fixed; + +----------------------------------------------------------------------------- +-- Visible functions +----------------------------------------------------------------------------- + + -- casting functions. These are needed for synthesis where typically + -- the only input and output type is a std_logic_vector. + function to_slv ( + arg : ufixed) -- fixed point vector + return STD_LOGIC_VECTOR is + subtype t is STD_LOGIC_VECTOR (arg'high - arg'low downto 0); + variable slv : t; + begin + if arg'length < 1 then + return NSLV; + end if; + slv := t (arg); + return slv; + end function to_slv; + + function to_slv ( + arg : sfixed) -- fixed point vector + return STD_LOGIC_VECTOR is + subtype t is STD_LOGIC_VECTOR (arg'high - arg'low downto 0); + variable slv : t; + begin + if arg'length < 1 then + return NSLV; + end if; + slv := t (arg); + return slv; + end function to_slv; + + function to_sulv ( + arg : ufixed) -- fixed point vector + return STD_ULOGIC_VECTOR is + begin + return to_stdulogicvector (to_slv(arg)); + end function to_sulv; + + function to_sulv ( + arg : sfixed) -- fixed point vector + return STD_ULOGIC_VECTOR is + begin + return to_stdulogicvector (to_slv(arg)); + end function to_sulv; + + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); + begin + if (arg'length < 1 or right_index > left_index) then + return NAUF; + end if; + if (arg'length /= result'length) then + report "FIXED_GENERIC_PKG.TO_UFIXED (STD_LOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NAUF; + else + result := to_fixed (arg => UNSIGNED(arg), + left_index => left_index, + right_index => right_index); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); + begin + if (arg'length < 1 or right_index > left_index) then + return NASF; + end if; + if (arg'length /= result'length) then + report "FIXED_GENERIC_PKG.TO_SFIXED (STD_LOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NASF; + else + result := to_fixed (arg => SIGNED(arg), + left_index => left_index, + right_index => right_index); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + begin + return to_ufixed (arg => to_stdlogicvector(arg), + left_index => left_index, + right_index => right_index); + end function to_ufixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + begin + return to_sfixed (arg => to_stdlogicvector(arg), + left_index => left_index, + right_index => right_index); + end function to_sfixed; + + -- Two's complement number, Grows the vector by 1 bit. + -- because "abs (1000.000) = 01000.000" or abs(-16) = 16. + function "abs" ( + arg : sfixed) -- fixed point input + return sfixed is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable ressns : SIGNED (arg'length downto 0); + variable result : sfixed (left_index+1 downto right_index); + begin + if (arg'length < 1 or result'length < 1) then + return NASF; + end if; + ressns (arg'length-1 downto 0) := to_s (cleanvec (arg)); + ressns (arg'length) := ressns (arg'length-1); -- expand sign bit + result := to_fixed (abs(ressns), left_index+1, right_index); + return result; + end function "abs"; + + -- also grows the vector by 1 bit. + function "-" ( + arg : sfixed) -- fixed point input + return sfixed is + constant left_index : INTEGER := arg'high+1; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable ressns : SIGNED (arg'length downto 0); + variable result : sfixed (left_index downto right_index); + begin + if (arg'length < 1 or result'length < 1) then + return NASF; + end if; + ressns (arg'length-1 downto 0) := to_s (cleanvec(arg)); + ressns (arg'length) := ressns (arg'length-1); -- expand sign bit + result := to_fixed (-ressns, left_index, right_index); + return result; + end function "-"; + + function "abs" (arg : sfixed) return ufixed is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := mine(arg'low, arg'low); + variable xarg : sfixed(left_index+1 downto right_index); + variable result : ufixed(left_index downto right_index); + begin + if arg'length < 1 then + return NAUF; + end if; + xarg := abs(arg); + result := ufixed (xarg (left_index downto right_index)); + return result; + end function "abs"; + + -- Addition + function "+" ( + l, r : ufixed) -- ufixed(a downto b) + ufixed(c downto d) = + return ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable result : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + begin + if (l'length < 1 or r'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv + rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "+"; + + function "+" ( + l, r : sfixed) -- sfixed(a downto b) + sfixed(c downto d) = + return sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable result : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index downto 0); + variable result_slv : SIGNED (left_index-right_index downto 0); + begin + if (l'length < 1 or r'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv + rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "+"; + + -- Subtraction + function "-" ( + l, r : ufixed) -- ufixed(a downto b) - ufixed(c downto d) = + return ufixed is -- ufixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable result : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + begin + if (l'length < 1 or r'length < 1) then + return NAUF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv - rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "-"; + + function "-" ( + l, r : sfixed) -- sfixed(a downto b) - sfixed(c downto d) = + return sfixed is -- sfixed(max(a,c)+1 downto min(b,d)) + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable result : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index downto 0); + variable result_slv : SIGNED (left_index-right_index downto 0); + begin + if (l'length < 1 or r'length < 1) then + return NASF; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv - rslv; + result := to_fixed(result_slv, left_index, right_index); + return result; + end function "-"; + + function "*" ( + l, r : ufixed) -- ufixed(a downto b) * ufixed(c downto d) = + return ufixed is -- ufixed(a+c+1 downto b+d) + variable lslv : UNSIGNED (l'length-1 downto 0); + variable rslv : UNSIGNED (r'length-1 downto 0); + variable result_slv : UNSIGNED (r'length+l'length-1 downto 0); + variable result : ufixed (l'high + r'high+1 downto + mine(l'low, l'low) + mine(r'low, r'low)); + begin + if (l'length < 1 or r'length < 1 or + result'length /= result_slv'length) then + return NAUF; + end if; + lslv := to_uns (cleanvec(l)); + rslv := to_uns (cleanvec(r)); + result_slv := lslv * rslv; + result := to_fixed (result_slv, result'high, result'low); + return result; + end function "*"; + + function "*" ( + l, r : sfixed) -- sfixed(a downto b) * sfixed(c downto d) = + return sfixed is -- sfixed(a+c+1 downto b+d) + variable lslv : SIGNED (l'length-1 downto 0); + variable rslv : SIGNED (r'length-1 downto 0); + variable result_slv : SIGNED (r'length+l'length-1 downto 0); + variable result : sfixed (l'high + r'high+1 downto + mine(l'low, l'low) + mine(r'low, r'low)); + begin + if (l'length < 1 or r'length < 1 or + result'length /= result_slv'length) then + return NASF; + end if; + lslv := to_s (cleanvec(l)); + rslv := to_s (cleanvec(r)); + result_slv := lslv * rslv; + result := to_fixed (result_slv, result'high, result'low); + return result; + end function "*"; + + function "/" ( + l, r : ufixed) -- ufixed(a downto b) / ufixed(c downto d) = + return ufixed is -- ufixed(a-d downto b-c-1) + begin + return divide (l, r); + end function "/"; + + function "/" ( + l, r : sfixed) -- sfixed(a downto b) / sfixed(c downto d) = + return sfixed is -- sfixed(a-d+1 downto b-c) + begin + return divide (l, r); + end function "/"; + + -- This version of divide gives the user more control + -- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1) + function divide ( + l, r : ufixed; + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return ufixed is + variable result : ufixed (l'high - mine(r'low, r'low) + downto mine (l'low, l'low) - r'high -1); + variable dresult : ufixed (result'high downto result'low -guard_bits); + variable lresize : ufixed (l'high downto l'high - dresult'length+1); + variable lslv : UNSIGNED (lresize'length-1 downto 0); + variable rslv : UNSIGNED (r'length-1 downto 0); + variable result_slv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NAUF; + end if; + lresize := resize (l, lresize'high, lresize'low); + lslv := to_uns (cleanvec (lresize)); + rslv := to_uns (cleanvec (r)); + if (rslv = 0) then + report "FIXED_GENERIC_PKG.DIVIDE uFixed point Division by zero" severity error; + result := saturate (result'high, result'low); -- saturate + else + result_slv := lslv / rslv; + dresult := to_fixed (result_slv, dresult'high, dresult'low); + result := resize (arg => dresult, + left_index => result'high, + right_index => result'low, + round_style => round_style, + overflow_style => fixed_wrap); -- overflow impossible + end if; + return result; + end function divide; + + -- sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c) + function divide ( + l, r : sfixed; + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return sfixed is + variable result : sfixed (l'high - mine(r'low, r'low)+1 + downto mine (l'low, l'low) - r'high); + variable dresult : sfixed (result'high downto result'low-guard_bits); + variable lresize : sfixed (l'high+1 downto l'high+1 -dresult'length+1); + variable lslv : SIGNED (lresize'length-1 downto 0); + variable rslv : SIGNED (r'length-1 downto 0); + variable result_slv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NASF; + end if; + lresize := resize (l, lresize'high, lresize'low); + lslv := to_s (cleanvec (lresize)); + rslv := to_s (cleanvec (r)); + if (rslv = 0) then + report "FIXED_GENERIC_PKG.DIVIDE uFixed point Division by zero" severity error; + result := saturate (result'high, result'low); + else + result_slv := lslv / rslv; + dresult := to_fixed (result_slv, dresult'high, dresult'low); + result := resize (arg => dresult, + left_index => result'high, + right_index => result'low, + round_style => round_style, + overflow_style => fixed_wrap); -- overflow impossible + end if; + return result; + end function divide; + + -- 1 / ufixed(a downto b) = ufixed(-b downto -a-1) + function reciprocal ( + arg : ufixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return ufixed is + constant one : ufixed (0 downto 0) := "1"; + begin + return divide(l => one, + r => arg, + round_style => round_style, + guard_bits => guard_bits); + end function reciprocal; + + -- 1 / sfixed(a downto b) = sfixed(-b+1 downto -a) + function reciprocal ( + arg : sfixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style; + constant guard_bits : NATURAL := fixed_guard_bits) + return sfixed is + constant one : sfixed (1 downto 0) := "01"; -- extra bit. + variable resultx : sfixed (-mine(arg'low, arg'low)+2 downto -arg'high); + begin + if (arg'length < 1 or resultx'length < 1) then + return NASF; + else + resultx := divide(l => one, + r => arg, + round_style => round_style, + guard_bits => guard_bits); + return resultx (resultx'high-1 downto resultx'low); -- remove extra bit + end if; + end function reciprocal; + + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) + function "rem" ( + l, r : ufixed) -- fixed point input + return ufixed is + begin + return remainder (l => l, + r => r, + round_style => fixed_round_style); + end function "rem"; + + -- remainder + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (min(a,c) downto min(b,d)) + function "rem" ( + l, r : sfixed) -- fixed point input + return sfixed is + begin + return remainder (l => l, + r => r, + round_style => fixed_round_style); + end function "rem"; + + -- ufixed (a downto b) rem ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b,d)) + function remainder ( + l, r : ufixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style) + return ufixed is + variable result : ufixed (minimum(l'high, r'high) downto mine(l'low, r'low)); + variable dresult : ufixed (r'high downto r'low); + variable lresize : ufixed (maximum(l'high, r'low) downto mins(r'low, r'low)); + variable lslv : UNSIGNED (lresize'length-1 downto 0); + variable rslv : UNSIGNED (r'length-1 downto 0); + variable result_slv : UNSIGNED (rslv'range); + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NAUF; + end if; + lresize := resize (arg => l, + left_index => lresize'high, + right_index => lresize'low, + overflow_style => fixed_wrap, -- vector only grows + round_style => fixed_truncate); + lslv := to_uns (lresize); + rslv := to_uns (cleanvec(r)); + if (rslv = 0) then + report "FIXED_GENERIC_PKG.rem uFixed point Division by zero" severity error; + result := saturate (result'high, result'low); -- saturate + else + if (r'low <= l'high) then + result_slv := lslv rem rslv; + dresult := to_fixed (result_slv, dresult'high, dresult'low); + result := resize (arg => dresult, + left_index => result'high, + right_index => result'low, + overflow_style => fixed_wrap, + round_style => round_style); +-- result(result'high downto r'low) := dresult(result'high downto r'low); + end if; + if l'low < r'low then + result(mins(r'low-1, l'high) downto l'low) := + cleanvec(l(mins(r'low-1, l'high) downto l'low)); + end if; + end if; + return result; + end function remainder; + + -- remainder + -- sfixed (a downto b) rem sfixed (c downto d) + -- = sfixed (min(a,c) downto min(b,d)) + function remainder ( + l, r : sfixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style) + return sfixed is + variable l_abs : ufixed (l'range); + variable r_abs : ufixed (r'range); + variable result : sfixed (minimum(r'high, l'high) downto mine(r'low, l'low)); + variable neg_result : sfixed (minimum(r'high, l'high)+1 downto mins(r'low, l'low)); + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NASF; + end if; + l_abs := abs(l); + r_abs := abs(r); + result := sfixed(remainder (l => l_abs, + r => r_abs, + round_style => round_style)); + neg_result := -result; + if l(l'high) = '1' then + result := neg_result(result'range); + end if; + return result; + end function remainder; + + -- modulo + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b, d)) + function "mod" ( + l, r : ufixed) -- fixed point input + return ufixed is + begin + return modulo (l => l, + r => r, + round_style => fixed_round_style); + end function "mod"; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto min(b, d)) + function "mod" ( + l, r : sfixed) -- fixed point input + return sfixed is + begin + return modulo(l => l, + r => r, + round_style => fixed_round_style); + end function "mod"; + + -- modulo + -- ufixed (a downto b) mod ufixed (c downto d) + -- = ufixed (min(a,c) downto min(b, d)) + function modulo ( + l, r : ufixed; -- fixed point input + constant round_style : BOOLEAN := fixed_round_style) + return ufixed is + begin + return remainder(l => l, + r => r, + round_style => round_style); + end function modulo; + + -- sfixed (a downto b) mod sfixed (c downto d) + -- = sfixed (c downto min(b, d)) + function modulo ( + l, r : sfixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; + constant round_style : BOOLEAN := fixed_round_style) + return sfixed is + variable l_abs : ufixed (l'range); + variable r_abs : ufixed (r'range); + variable result : sfixed (r'high downto + mine(r'low, l'low)); + variable dresult : sfixed (minimum(r'high, l'high)+1 downto + mins(r'low, l'low)); + variable dresult_not_zero : BOOLEAN; + begin + if (l'length < 1 or r'length < 1 or + mins(r'low, r'low) /= r'low or mins(l'low, l'low) /= l'low) then + return NASF; + end if; + l_abs := abs(l); + r_abs := abs(r); + dresult := "0" & sfixed(remainder (l => l_abs, + r => r_abs, + round_style => round_style)); + if (to_s(dresult) = 0) then + dresult_not_zero := false; + else + dresult_not_zero := true; + end if; + if to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '0' + and dresult_not_zero then + result := resize (arg => r - dresult, + left_index => result'high, + right_index => result'low, + overflow_style => overflow_style, + round_style => round_style); + elsif to_x01(l(l'high)) = '1' and to_x01(r(r'high)) = '1' then + result := resize (arg => -dresult, + left_index => result'high, + right_index => result'low, + overflow_style => overflow_style, + round_style => round_style); + elsif to_x01(l(l'high)) = '0' and to_x01(r(r'high)) = '1' + and dresult_not_zero then + result := resize (arg => dresult + r, + left_index => result'high, + right_index => result'low, + overflow_style => overflow_style, + round_style => round_style); + else + result := resize (arg => dresult, + left_index => result'high, + right_index => result'low, + overflow_style => overflow_style, + round_style => round_style); + end if; + return result; + end function modulo; + + -- Procedure for those who need an "accumulator" function + procedure add_carry ( + L, R : in ufixed; + c_in : in STD_ULOGIC; + result : out ufixed; + c_out : out STD_ULOGIC) is + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (left_index-right_index + downto 0); + variable result_slv : UNSIGNED (left_index-right_index + downto 0); + variable cx : UNSIGNED (0 downto 0); -- Carry in + begin + if (l'length < 1 or r'length < 1) then + result := NAUF; + c_out := '0'; + else + cx (0) := c_in; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + result_slv := lslv + rslv + cx; + c_out := result_slv(left_index); + result := to_fixed(result_slv (left_index-right_index-1 downto 0), + left_index-1, right_index); + end if; + end procedure add_carry; + + procedure add_carry ( + L, R : in sfixed; + c_in : in STD_ULOGIC; + result : out sfixed; + c_out : out STD_ULOGIC) is + constant left_index : INTEGER := maximum(l'high, r'high)+1; + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (left_index-right_index + downto 0); + variable result_slv : SIGNED (left_index-right_index + downto 0); + variable cx : SIGNED (1 downto 0); -- Carry in + begin + if (l'length < 1 or r'length < 1) then + result := NASF; + c_out := '0'; + else + cx (1) := '0'; + cx (0) := c_in; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + result_slv := lslv + rslv + cx; + c_out := result_slv(left_index); + result := to_fixed(result_slv (left_index-right_index-1 downto 0), + left_index-1, right_index); + end if; + end procedure add_carry; + + -- Scales the result by a power of 2. Width of input = width of output with + -- the decimal point moved. + function scalb (y : ufixed; N : integer) return ufixed is + variable result : ufixed (y'high+N downto y'low+N); + begin + if y'length < 1 then + return NAUF; + else + result := y; + return result; + end if; + end function scalb; + + function scalb (y : ufixed; N : SIGNED) return ufixed is + begin + return scalb (y => y, + N => to_integer(N)); + end function scalb; + + function scalb (y : sfixed; N : integer) return sfixed is + variable result : sfixed (y'high+N downto y'low+N); + begin + if y'length < 1 then + return NASF; + else + result := y; + return result; + end if; + end function scalb; + + function scalb (y : sfixed; N : SIGNED) return sfixed is + begin + return scalb (y => y, + N => to_integer(N)); + end function scalb; + + function Is_Negative (arg : sfixed) return BOOLEAN is + begin + if to_X01(arg(arg'high)) = '1' then + return true; + else + return false; + end if; + end function Is_Negative; + + function find_lsb (arg : ufixed; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'low to arg'high loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_lsb; + + function find_msb (arg : ufixed; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'high downto arg'low loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_msb; + + function find_lsb (arg : sfixed; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'low to arg'high loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_lsb; + + function find_msb (arg : sfixed; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'high downto arg'low loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_msb; + + function "sll" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sll"; + + function "srl" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "srl"; + + function "rol" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv rol COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "rol"; + + function "ror" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + argslv := argslv ror COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "ror"; + + function "sla" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + -- Arithmetic shift on an unsigned is a logical shift + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sla"; + + function "sra" (ARG : ufixed; COUNT : INTEGER) return ufixed is + variable argslv : UNSIGNED (arg'length-1 downto 0); + variable result : ufixed (arg'range); + begin + argslv := to_uns (arg); + -- Arithmetic shift on an unsigned is a logical shift + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sra"; + + function "sll" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv sll COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sll"; + + function "srl" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv srl COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "srl"; + + function "rol" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv rol COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "rol"; + + function "ror" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + argslv := argslv ror COUNT; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "ror"; + + function "sla" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + if COUNT > 0 then + -- Arithmetic shift left on a 2's complement number is a logic shift + argslv := argslv sll COUNT; + else + argslv := argslv sra -COUNT; + end if; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sla"; + + function "sra" (ARG : sfixed; COUNT : INTEGER) return sfixed is + variable argslv : SIGNED (arg'length-1 downto 0); + variable result : sfixed (arg'range); + begin + argslv := to_s (arg); + if COUNT > 0 then + argslv := argslv sra COUNT; + else + -- Arithmetic shift left on a 2's complement number is a logic shift + argslv := argslv sll -COUNT; + end if; + result := to_fixed (argslv, result'high, result'low); + return result; + end function "sra"; + + -- Because some people want the older functions. + function SHIFT_LEFT (ARG : ufixed; COUNT : NATURAL) return ufixed is + begin + if (ARG'length < 1) then + return NAUF; + end if; + return ARG sla COUNT; + end function SHIFT_LEFT; + function SHIFT_RIGHT (ARG : ufixed; COUNT : NATURAL) return ufixed is + begin + if (ARG'length < 1) then + return NAUF; + end if; + return ARG sra COUNT; + end function SHIFT_RIGHT; + function SHIFT_LEFT (ARG : sfixed; COUNT : NATURAL) return sfixed is + begin + if (ARG'length < 1) then + return NASF; + end if; + return ARG sla COUNT; + end function SHIFT_LEFT; + function SHIFT_RIGHT (ARG : sfixed; COUNT : NATURAL) return sfixed is + begin + if (ARG'length < 1) then + return NASF; + end if; + return ARG sra COUNT; + end function SHIFT_RIGHT; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_slv(L); + return to_ufixed(RESULT, L'high, L'low); + end function "not"; + + function "and" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) and to_slv(R); + else + report "FIXED_GENERIC_PKG.""and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "and"; + + function "or" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) or to_slv(R); + else + report "FIXED_GENERIC_PKG.""or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "or"; + + function "nand" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) nand to_slv(R); + else + report "FIXED_GENERIC_PKG.""nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "nand"; + + function "nor" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) nor to_slv(R); + else + report "FIXED_GENERIC_PKG.""nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "nor"; + + function "xor" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) xor to_slv(R); + else + report "FIXED_GENERIC_PKG.""xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "xor"; + + function "xnor" (L, R : ufixed) return ufixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) xnor to_slv(R); + else + report "FIXED_GENERIC_PKG.""xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_ufixed(RESULT, L'high, L'low); + end function "xnor"; + + function "not" (L : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + RESULT := not to_slv(L); + return to_sfixed(RESULT, L'high, L'low); + end function "not"; + + function "and" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) and to_slv(R); + else + report "FIXED_GENERIC_PKG.""and"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "and"; + + function "or" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) or to_slv(R); + else + report "FIXED_GENERIC_PKG.""or"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "or"; + + function "nand" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) nand to_slv(R); + else + report "FIXED_GENERIC_PKG.""nand"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "nand"; + + function "nor" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) nor to_slv(R); + else + report "FIXED_GENERIC_PKG.""nor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "nor"; + + function "xor" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) xor to_slv(R); + else + report "FIXED_GENERIC_PKG.""xor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "xor"; + + function "xnor" (L, R : sfixed) return sfixed is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + begin + if (L'high = R'high and L'low = R'low) then + RESULT := to_slv(L) xnor to_slv(R); + else + report "FIXED_GENERIC_PKG.""xnor"": Range error L'RANGE /= R'RANGE" + severity warning; + RESULT := (others => 'U'); + end if; + return to_sfixed(RESULT, L'high, L'low); + end function "xnor"; + + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L and R(i); + end loop; + return result; + end function "and"; + + function "and" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) and R; + end loop; + return result; + end function "and"; + + function "or" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L or R(i); + end loop; + return result; + end function "or"; + + function "or" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) or R; + end loop; + return result; + end function "or"; + + function "nand" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L nand R(i); + end loop; + return result; + end function "nand"; + + function "nand" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nand R; + end loop; + return result; + end function "nand"; + + function "nor" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L nor R(i); + end loop; + return result; + end function "nor"; + + function "nor" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nor R; + end loop; + return result; + end function "nor"; + + function "xor" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L xor R(i); + end loop; + return result; + end function "xor"; + + function "xor" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xor R; + end loop; + return result; + end function "xor"; + + function "xnor" (L : STD_ULOGIC; R : ufixed) return ufixed is + variable result : ufixed (R'range); + begin + for i in result'range loop + result(i) := L xnor R(i); + end loop; + return result; + end function "xnor"; + + function "xnor" (L : ufixed; R : STD_ULOGIC) return ufixed is + variable result : ufixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + function "and" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L and R(i); + end loop; + return result; + end function "and"; + + function "and" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) and R; + end loop; + return result; + end function "and"; + + function "or" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L or R(i); + end loop; + return result; + end function "or"; + + function "or" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) or R; + end loop; + return result; + end function "or"; + + function "nand" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L nand R(i); + end loop; + return result; + end function "nand"; + + function "nand" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nand R; + end loop; + return result; + end function "nand"; + + function "nor" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L nor R(i); + end loop; + return result; + end function "nor"; + + function "nor" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) nor R; + end loop; + return result; + end function "nor"; + + function "xor" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L xor R(i); + end loop; + return result; + end function "xor"; + + function "xor" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xor R; + end loop; + return result; + end function "xor"; + + function "xnor" (L : STD_ULOGIC; R : sfixed) return sfixed is + variable result : sfixed (R'range); + begin + for i in result'range loop + result(i) := L xnor R(i); + end loop; + return result; + end function "xnor"; + + function "xnor" (L : sfixed; R : STD_ULOGIC) return sfixed is + variable result : sfixed (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + -- Reduction operators, same as numeric_std functions + -- %%% remove 12 functions (old syntax) + function and_reduce(arg : ufixed) return STD_ULOGIC is + begin + return and_reducex (to_slv(arg)); + end function and_reduce; + + function nand_reduce(arg : ufixed) return STD_ULOGIC is + begin + return not and_reducex (to_slv(arg)); + end function nand_reduce; + + function or_reduce(arg : ufixed) return STD_ULOGIC is + begin + return or_reducex (to_slv(arg)); + end function or_reduce; + + function nor_reduce(arg : ufixed) return STD_ULOGIC is + begin + return not or_reducex (to_slv(arg)); + end function nor_reduce; + + function xor_reduce(arg : ufixed) return STD_ULOGIC is + begin + return xor_reducex (to_slv(arg)); + end function xor_reduce; + + function xnor_reduce(arg : ufixed) return STD_ULOGIC is + begin + return not xor_reducex (to_slv(arg)); + end function xnor_reduce; + + function and_reduce(arg : sfixed) return STD_ULOGIC is + begin + return and_reducex (to_slv(arg)); + end function and_reduce; + + function nand_reduce(arg : sfixed) return STD_ULOGIC is + begin + return not and_reducex (to_slv(arg)); + end function nand_reduce; + + function or_reduce(arg : sfixed) return STD_ULOGIC is + begin + return or_reducex (to_slv(arg)); + end function or_reduce; + + function nor_reduce(arg : sfixed) return STD_ULOGIC is + begin + return not or_reducex (to_slv(arg)); + end function nor_reduce; + + function xor_reduce(arg : sfixed) return STD_ULOGIC is + begin + return xor_reducex (to_slv(arg)); + end function xor_reduce; + + function xnor_reduce(arg : sfixed) return STD_ULOGIC is + begin + return not xor_reducex (to_slv(arg)); + end function xnor_reduce; + -- %%% Uncomment the following 12 functions (new syntax) + -- function "and" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return and to_slv(arg); + -- end function "and"; + -- function "nand" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return nand to_slv(arg); + -- end function "nand";; + -- function "or" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return or to_slv(arg); + -- end function "or"; + -- function "nor" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return nor to_slv(arg); + -- end function "nor"; + -- function "xor" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return xor to_slv(arg); + -- end function "xor"; + -- function "xnor" ( arg : ufixed ) RETURN std_ulogic is + -- begin + -- return xnor to_slv(arg); + -- end function "xnor"; + -- function "and" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return and to_slv(arg); + -- end function "and";; + -- function "nand" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return nand to_slv(arg); + -- end function "nand";; + -- function "or" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return or to_slv(arg); + -- end function "or"; + -- function "nor" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return nor to_slv(arg); + -- end function "nor"; + -- function "xor" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return xor to_slv(arg); + -- end function "xor"; + -- function "xnor" ( arg : sfixed ) RETURN std_ulogic is + -- begin + -- return xnor to_slv(arg); + -- end function "xnor"; + + -- %%% Replace with the following (new syntax) +-- function "?=" (L, R : ufixed) return STD_ULOGIC is + function \?=\ (L, R : ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + result := '1'; + for i in lresize'reverse_range loop + result1 := \?=\(lresize(i), rresize(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; +-- end function "?="; + +-- function "?/=" (L, R : ufixed) return STD_ULOGIC is + function \?/=\ (L, R : ufixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?/= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + result := '0'; + for i in lresize'reverse_range loop + result1 := \?/=\ (lresize(i), rresize(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; +-- end function "?/="; + +-- function "?>" (L, R : ufixed) return STD_ULOGIC is + function \?>\ (L, R : ufixed) return STD_ULOGIC is + begin -- ?> + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?>"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; +-- end function "?>"; + +-- function "?>=" (L, R : ufixed) return STD_ULOGIC is + function \?>=\ (L, R : ufixed) return STD_ULOGIC is + begin -- ?>= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?>="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; +-- end function "?>="; + +-- function "?<" (L, R : ufixed) return STD_ULOGIC is + function \?<\ (L, R : ufixed) return STD_ULOGIC is + begin -- ?< + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?<"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; +-- end function "?<"; + +-- function "?<=" (L, R : ufixed) return STD_ULOGIC is + function \?<=\ (L, R : ufixed) return STD_ULOGIC is + begin -- ?<= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?<="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; +-- end function "?<="; + + -- function "?=" (L, R : sfixed) return STD_ULOGIC is + function \?=\ (L, R : sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + result := '1'; + for i in lresize'reverse_range loop + result1 := \?=\ (lresize(i), rresize(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result and result1; + end if; + end loop; + return result; + end if; + end function \?=\; +-- end function "?="; + +-- function "?/=" (L, R : sfixed) return STD_ULOGIC is + function \?/=\ (L, R : sfixed) return STD_ULOGIC is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable result, result1 : STD_ULOGIC; -- result + begin -- ?/= + if ((L'LENGTH < 1) or (R'LENGTH < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?/="": null detected, returning X" + severity warning; + return 'X'; + else + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + result := '0'; + for i in lresize'reverse_range loop + result1 := \?/=\ (lresize(i), rresize(i)); + if result1 = 'U' then + return 'U'; + elsif result1 = 'X' or result = 'X' then + result := 'X'; + else + result := result or result1; + end if; + end loop; + return result; + end if; + end function \?/=\; +-- end function "?/="; + +-- function "?>" (L, R : sfixed) return STD_ULOGIC is + function \?>\ (L, R : sfixed) return STD_ULOGIC is + begin -- ?> + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?>"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; +-- end function "?>"; + +-- function "?>=" (L, R : sfixed) return STD_ULOGIC is + function \?>=\ (L, R : sfixed) return STD_ULOGIC is + begin -- ?>= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?>="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; +-- end function "?>="; + +-- function "?<" (L, R : sfixed) return STD_ULOGIC is + function \?<\ (L, R : sfixed) return STD_ULOGIC is + begin -- ?< + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?<"": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; +-- end function "?<"; + +-- function "?<=" (L, R : sfixed) return STD_ULOGIC is + function \?<=\ (L, R : sfixed) return STD_ULOGIC is + begin -- ?<= + if ((l'length < 1) or (r'length < 1)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""?<="": null detected, returning X" + severity warning; + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) or (find_msb (r, '-') /= r'low-1) then + report "FIXED_GENERIC_PKG.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; +-- end function "?<="; + + -- %%% end replace + -- Match function, similar to "std_match" from numeric_std + function std_match (L, R : ufixed) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_slv(L), to_slv(R)); + else + report "FIXED_GENERIC_PKG.STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + + function std_match (L, R : sfixed) return BOOLEAN is + begin + if (L'high = R'high and L'low = R'low) then + return std_match(to_slv(L), to_slv(R)); + else + report "FIXED_GENERIC_PKG.STD_MATCH: L'RANGE /= R'RANGE, returning FALSE" + severity warning; + return false; + end if; + end function std_match; + --%%% end remove + + -- compare functions + function "=" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv = rslv; + end function "="; + + function "=" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv = rslv; + end function "="; + + function "/=" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""/="": null argument detected, returning TRUE" + severity warning; + return true; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""/="": metavalue detected, returning TRUE" + severity warning; + return true; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv /= rslv; + end function "/="; + + function "/=" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""/="": null argument detected, returning TRUE" + severity warning; + return true; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""/="": metavalue detected, returning TRUE" + severity warning; + return true; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv /= rslv; + end function "/="; + + function ">" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv > rslv; + end function ">"; + + function ">" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv > rslv; + end function ">"; + + function "<" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv < rslv; + end function "<"; + + function "<" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<"": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<"": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv < rslv; + end function "<"; + + function ">=" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv >= rslv; + end function ">="; + + function ">=" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG."">="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv >= rslv; + end function ">="; + + function "<=" ( + l, r : ufixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : ufixed (left_index downto right_index); + variable lslv, rslv : UNSIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_uns (lresize); + rslv := to_uns (rresize); + return lslv <= rslv; + end function "<="; + + function "<=" ( + l, r : sfixed) -- fixed point input + return BOOLEAN is + constant left_index : INTEGER := maximum(l'high, r'high); + constant right_index : INTEGER := mins(l'low, r'low); + variable lresize, rresize : sfixed (left_index downto right_index); + variable lslv, rslv : SIGNED (lresize'length-1 downto 0); + begin + if (l'length < 1 or r'length < 1) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<="": null argument detected, returning FALSE" + severity warning; + return false; + elsif (Is_X(l) or Is_X(r)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.""<="": metavalue detected, returning FALSE" + severity warning; + return false; + end if; + lresize := resize (l, left_index, right_index); + rresize := resize (r, left_index, right_index); + lslv := to_s (lresize); + rslv := to_s (rresize); + return lslv <= rslv; + end function "<="; + + -- overloads of the default maximum and minimum functions + function maximum (l, r : ufixed) return ufixed is + begin + if l > r then return l; + else return r; + end if; + end function maximum; + + function maximum (l, r : sfixed) return sfixed is + begin + if l > r then return l; + else return r; + end if; + end function maximum; + + function minimum (l, r : ufixed) return ufixed is + begin + if l > r then return r; + else return l; + end if; + end function minimum; + + function minimum (l, r : sfixed) return sfixed is + begin + if l > r then return r; + else return l; + end if; + end function minimum; + + function to_ufixed ( + arg : NATURAL; -- integer + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return ufixed is + variable argx : INTEGER; + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : ufixed (left_index downto fw) := (others => '0'); + variable sresult : UNSIGNED (left_index downto 0); -- integer portion + variable bound : NATURAL; -- find the numerical bounds + begin + if (left_index < fw) then + return NAUF; + end if; + if left_index >= 0 then + if (left_index < 30) then + bound := 2**(left_index+1); + else + bound := INTEGER'high; + end if; + end if; + if (arg /= 0) then + if arg >= bound or left_index < 0 then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_UFIXED(NATURAL): vector truncated" + severity warning; + if (overflow_style = fixed_wrap) then -- wrap + if bound = 0 then + argx := 0; + else + argx := arg mod bound; + end if; + else -- saturate + return saturate (result'high, result'low); + end if; + else + argx := arg; + end if; + else + return result; -- return zero + end if; + sresult := to_unsigned (argx, sresult'high+1); + result := resize (arg => ufixed (sresult), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_ufixed; + + function to_sfixed ( + arg : INTEGER; -- integer + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return sfixed is + variable argx : INTEGER; + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : sfixed (left_index downto fw) := (others => '0'); + variable sresult : SIGNED (left_index+1 downto 0); -- integer portion + variable bound : NATURAL := 0; + begin + if (left_index < fw) then -- null range + return NASF; + end if; + if left_index >= 0 then + if (left_index < 30) then + bound := 2**(left_index); + else + bound := INTEGER'high; + end if; + end if; + if (arg /= 0) then + if (arg >= bound or arg < -bound or left_index < 0) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_SFIXED(INTEGER): vector truncated" + severity warning; + if overflow_style = fixed_wrap then -- wrap + if bound = 0 then -- negative integer_range trap + argx := 0; + else -- shift off the top bits + argx := arg rem (bound*2); + end if; + else -- saturate + if arg < 0 then + result := not saturate (result'high, result'low); -- underflow + else + result := saturate (result'high, result'low); -- overflow + end if; + return result; + end if; + else + argx := arg; + end if; + else + return result; -- return zero + end if; + sresult := to_signed (argx, sresult'length); + result := resize (arg => sfixed (sresult), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_sfixed; + + function to_ufixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return ufixed is + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : ufixed (left_index downto fw) := (others => '0'); + variable Xresult : ufixed (left_index downto fw-guard_bits) := (others => '0'); + variable presult : REAL; + variable overflow_needed : BOOLEAN; + begin + -- If negative or null range, return. + if (left_index < fw) then + return NAUF; + end if; + if (arg < 0.0) then + report "FIXED_GENERIC_PKG.TO_UFIXED: Negative argument passed " + & REAL'image(arg) severity error; + return result; + end if; + presult := arg; + if presult >= (2.0**(left_index+1)) then + assert NO_WARNING report "FIXED_GENERIC_PKG.TO_UFIXED(REAL): vector truncated" + severity warning; + overflow_needed := (overflow_style = fixed_saturate); + if overflow_style = fixed_wrap then + presult := presult mod (2.0**(left_index+1)); -- wrap + else + return saturate (result'high, result'low); + end if; + end if; + for i in Xresult'range loop + if presult >= 2.0**i then + Xresult(i) := '1'; + presult := presult - 2.0**i; + else + Xresult(i) := '0'; + end if; + end loop; + if guard_bits > 0 and round_style = fixed_round then + result := round_fixed (arg => Xresult (left_index + downto right_index), + remainder => Xresult (right_index-1 downto + right_index-guard_bits), + overflow_style => overflow_style); + else + result := Xresult (result'range); + end if; + return result; + end function to_ufixed; + + function to_sfixed ( + arg : REAL; -- real + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return sfixed is + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : sfixed (left_index downto fw) := (others => '0'); + variable Xresult : sfixed (left_index+1 downto fw-guard_bits) := (others => '0'); + variable presult : REAL; + begin + if (left_index < fw) then -- null range + return NASF; + end if; + if (arg >= (2.0**left_index) or arg < -(2.0**left_index)) then + assert NO_WARNING report "FIXED_GENERIC_PKG.TO_SFIXED(REAL): vector truncated" + severity warning; + if overflow_style = fixed_saturate then + if arg < 0.0 then -- saturate + result := not saturate (result'high, result'low); -- underflow + else + result := saturate (result'high, result'low); -- overflow + end if; + return result; + else + presult := abs(arg) mod (2.0**(left_index+1)); -- wrap + end if; + else + presult := abs(arg); + end if; + for i in Xresult'range loop + if presult >= 2.0**i then + Xresult(i) := '1'; + presult := presult - 2.0**i; + else + Xresult(i) := '0'; + end if; + end loop; + if arg < 0.0 then + Xresult := to_fixed(-to_s(Xresult), Xresult'high, Xresult'low); + end if; + if guard_bits > 0 and round_style then + result := round_fixed (arg => Xresult (left_index + downto right_index), + remainder => Xresult (right_index-1 downto + right_index-guard_bits), + overflow_style => overflow_style); + else + result := Xresult (result'range); + end if; + return result; + end function to_sfixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return ufixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : ufixed (left_index downto fw); + begin + if arg'length < 1 or (left_index < fw) then + return NAUF; + end if; + result := resize (arg => ufixed (XARG), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_ufixed; + + -- casted version + function to_ufixed ( + arg : UNSIGNED) -- unsigned + return ufixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + begin + if arg'length < 1 then + return NAUF; + end if; + return ufixed(xarg); + end function to_ufixed; + + function to_sfixed ( + arg : SIGNED; -- signed + constant left_index : INTEGER; -- size of integer portion + constant right_index : INTEGER := 0; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return sfixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + constant fw : INTEGER := mine (right_index, right_index); -- catch literals + variable result : sfixed (left_index downto fw); + begin + if arg'length < 1 or (left_index < fw) then + return NASF; + end if; + result := resize (arg => sfixed (XARG), + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_sfixed; + + -- casted version + function to_sfixed ( + arg : SIGNED) -- signed + return sfixed is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + begin + if arg'length < 1 then + return NASF; + end if; + return sfixed(xarg); + end function to_sfixed; + + function add_sign (arg : ufixed) return sfixed is + variable result : sfixed (arg'high+1 downto arg'low); + begin + if arg'length < 1 then + return NASF; + end if; + result (arg'high downto arg'low) := sfixed(cleanvec(arg)); + result (arg'high+1) := '0'; + return result; + end function add_sign; + + -- Because of the farily complicated sizing rules in the fixed point + -- packages these functions are provided to compute the result ranges + -- Example: + -- signal uf1 : ufixed (3 downto -3); + -- signal uf2 : ufixed (4 downto -2); + -- signal uf1multuf2 : ufixed (ufixed_high (3, -3, '*', 4, -2) downto + -- ufixed_low (3, -3, '*', 4, -2)); + -- uf1multuf2 <= uf1 * uf2; + -- Valid characters: '+', '-', '*', '/', 'r' or 'R' (rem), 'm' or 'M' (mod), + -- '1' (reciprocal), 'A', 'a' (abs), 'N', 'n' (-sfixed) + function ufixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return maximum (left_index, left_index2) + 1; + when '*' => return left_index + left_index2 + 1; + when '/' => return left_index - right_index2; + when '1' => return -right_index; -- reciprocal + when 'R'|'r' => return mins (left_index, left_index2); -- "rem" + when 'M'|'m' => return mins (left_index, left_index2); -- "mod" + when others => return left_index; -- For abs and default + end case; + end function ufixed_high; + + function ufixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return mins (right_index, right_index2); + when '*' => return right_index + right_index2; + when '/' => return right_index - left_index2 - 1; + when '1' => return -left_index - 1; -- reciprocal + when 'R'|'r' => return mins (right_index, right_index2); -- "rem" + when 'M'|'m' => return mins (right_index, right_index2); -- "mod" + when others => return right_index; -- for abs and default + end case; + end function ufixed_low; + + function sfixed_high (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return maximum (left_index, left_index2) + 1; + when '*' => return left_index + left_index2 + 1; + when '/' => return left_index - right_index2 + 1; + when '1' => return -right_index + 1; -- reciprocal + when 'R'|'r' => return mins (left_index, left_index2); -- "rem" + when 'M'|'m' => return left_index2; -- "mod" + when 'A'|'a' => return left_index + 1; -- "abs" + when 'N'|'n' => return left_index + 1; -- -sfixed + when others => return left_index; + end case; + end function sfixed_high; + + function sfixed_low (left_index, right_index : INTEGER; + operation : CHARACTER := 'X'; + left_index2, right_index2 : INTEGER := 0) + return INTEGER is + begin + case operation is + when '+'| '-' => return mins (right_index, right_index2); + when '*' => return right_index + right_index2; + when '/' => return right_index - left_index2; + when '1' => return -left_index; -- reciprocal + when 'R'|'r' => return mins (right_index, right_index2); -- "rem" + when 'M'|'m' => return mins (right_index, right_index2); -- "mod" + when others => return right_index; -- default for abs, neg and default + end case; + end function sfixed_low; + -- Same as above, but using the "size_res" input only for their ranges: + -- signal uf1multuf2 : ufixed (ufixed_high (uf1, '*', uf2) downto + -- ufixed_low (uf1, '*', uf2)); + -- uf1multuf2 <= uf1 * uf2; + function ufixed_high (size_res : ufixed; + operation : CHARACTER := 'X'; + size_res2 : ufixed) + return INTEGER is + begin + return ufixed_high (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function ufixed_high; + function ufixed_low (size_res : ufixed; + operation : CHARACTER := 'X'; + size_res2 : ufixed) + return INTEGER is + begin + return ufixed_low (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function ufixed_low; + function sfixed_high (size_res : sfixed; + operation : CHARACTER := 'X'; + size_res2 : sfixed) + return INTEGER is + begin + return sfixed_high (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function sfixed_high; + function sfixed_low (size_res : sfixed; + operation : CHARACTER := 'X'; + size_res2 : sfixed) + return INTEGER is + begin + return sfixed_low (left_index => size_res'high, + right_index => size_res'low, + operation => operation, + left_index2 => size_res2'high, + right_index2 => size_res2'low); + end function sfixed_low; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + constant sat : ufixed (left_index downto right_index) := (others => '1'); + begin + return sat; + end function saturate; + + -- purpose: returns a saturated number + function saturate ( + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable sat : sfixed (left_index downto right_index) := (others => '1'); + begin + -- saturate positive, to saturate negative, just do "not saturate()" + sat (left_index) := '0'; + return sat; + end function saturate; + + function saturate ( + size_res : ufixed) -- only the size of this is used + return ufixed is + begin + return saturate (size_res'high, size_res'low); + end function saturate; + + function saturate ( + size_res : sfixed) -- only the size of this is used + return sfixed is + begin + return saturate (size_res'high, size_res'low); + end function saturate; + + -- As a concession to those who use a graphical DSP environment, + -- these functions take parameters in those tools format and create + -- fixed point numbers. These functions are designed to convert from + -- a std_logic_vector to the VHDL fixed point format using the conventions + -- of these packages. In a pure VHDL environment you should use the + -- "to_ufixed" and "to_sfixed" routines. + -- Unsigned fixed point + function to_UFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return ufixed is + variable result : ufixed (width-fraction-1 downto -fraction); + begin + if (arg'length /= result'length) then + report "FIXED_GENERIC_PKG.TO_UFIX (STD_LOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NAUF; + else + result := to_ufixed (arg, result'high, result'low); + return result; + end if; + end function to_UFix; + + -- signed fixed point + function to_SFix ( + arg : STD_LOGIC_VECTOR; + width : NATURAL; -- width of vector + fraction : NATURAL) -- width of fraction + return sfixed is + variable result : sfixed (width-fraction-1 downto -fraction); + begin + if (arg'length /= result'length) then + report "FIXED_GENERIC_PKG.TO_SFIX (STD_LOGIC_VECTOR) " + & "Vector lengths do not match. Input length is " + & INTEGER'image(arg'length) & " and output will be " + & INTEGER'image(result'length) & " wide." + severity error; + return NASF; + else + result := to_sfixed (arg, result'high, result'low); + return result; + end if; + end function to_SFix; + + -- finding the bounds of a number. These functions can be used like this: + -- signal xxx : ufixed (7 downto -3); + -- -- Which is the same as "ufixed (UFix_high (11,3) downto UFix_low(11,3))" + -- signal yyy : ufixed (UFix_high (11, 3, "+", 11, 3) + -- downto UFix_low(11, 3, "+", 11, 3)); + -- Where "11" is the width of xxx (xxx'length), + -- and 3 is the lower bound (abs (xxx'low)) + -- In a pure VHDL environment use "ufixed_high" and "ufixed_low" + function ufix_high ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return ufixed_high (left_index => width - 1 - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - 1 - fraction2, + right_index2 => -fraction2); + end function ufix_high; + function ufix_low ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return ufixed_low (left_index => width - 1 - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - 1 - fraction2, + right_index2 => -fraction2); + end function ufix_low; + function sfix_high ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return sfixed_high (left_index => width - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - fraction2, + right_index2 => -fraction2); + end function sfix_high; + function sfix_low ( + width, fraction : NATURAL; + operation : CHARACTER := 'X'; + width2, fraction2 : NATURAL := 0) + return INTEGER is + begin + return sfixed_low (left_index => width - fraction, + right_index => -fraction, + operation => operation, + left_index2 => width2 - fraction2, + right_index2 => -fraction2); + end function sfix_low; + + function to_unsigned ( + arg : ufixed; -- ufixed point input + constant size : NATURAL; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return UNSIGNED is + begin + return to_uns(resize (arg => arg, + left_index => size-1, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + end function to_unsigned; + + function to_unsigned ( + arg : ufixed; -- ufixed point input + size_res : UNSIGNED; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return UNSIGNED is + begin + return to_unsigned (arg => arg, + size => size_res'length, + round_style => round_style, + overflow_style => overflow_style); + end function to_unsigned; + + function to_signed ( + arg : sfixed; -- ufixed point input + constant size : NATURAL; -- length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return SIGNED is + begin + return to_s(resize (arg => arg, + left_index => size-1, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + end function to_signed; + + function to_signed ( + arg : sfixed; -- ufixed point input + size_res : SIGNED; -- used for length of output + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return SIGNED is + begin + return to_signed (arg => arg, + size => size_res'length, + round_style => round_style, + overflow_style => overflow_style); + end function to_signed; + + function to_real ( + arg : ufixed) -- ufixed point input + return REAL is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable result : REAL; -- result + variable arg_int : ufixed (left_index downto right_index); + begin + if (arg'length < 1) then + return 0.0; + end if; + arg_int := cleanvec(arg); + if (Is_X(arg_int)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_REAL: metavalue detected, returning 0.0" + severity warning; + return 0.0; + end if; + result := 0.0; + for i in arg_int'range loop + if (arg_int(i) = '1') then + result := result + (2.0**i); + end if; + end loop; + return result; + end function to_real; + + function to_real ( + arg : sfixed) -- ufixed point input + return REAL is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable result : REAL; -- result + variable arg_int : sfixed (left_index downto right_index); + -- unsigned version of argument + variable arg_uns : ufixed (left_index downto right_index); + -- absolute of argument + begin + if (arg'length < 1) then + return 0.0; + end if; + arg_int := cleanvec(arg); + if (Is_X(arg_int)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_REAL: metavalue detected, returning 0.0" + severity warning; + return 0.0; + end if; + arg_uns := abs(arg_int); + result := to_real (arg_uns); + if (arg_int(arg_int'high) = '1') then + result := -result; + end if; + return result; + end function to_real; + + function to_integer ( + arg : ufixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return NATURAL is + constant left_index : INTEGER := arg'high; + variable arg_uns : UNSIGNED (minimum(31, left_index+1) downto 0) + := (others => '0'); + begin + if (arg'length < 1) then + return 0; + end if; + if (Is_X (arg)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_INTEGER: metavalue detected, returning 0" + severity warning; + return 0; + end if; + if (left_index < -1) then + return 0; + end if; + arg_uns := to_uns(resize (arg => arg, + left_index => arg_uns'high, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + return to_integer (arg_uns); + end function to_integer; + + function to_integer ( + arg : sfixed; -- fixed point input + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- rounding by default + return INTEGER is + constant left_index : INTEGER := arg'high; + constant right_index : INTEGER := arg'low; + variable arg_s : SIGNED (minimum(31, left_index+1) downto 0); + begin + if (arg'length < 1) then + return 0; + end if; + if (Is_X (arg)) then + assert NO_WARNING + report "FIXED_GENERIC_PKG.TO_INTEGER: metavalue detected, returning 0" + severity warning; + return 0; + end if; + if (left_index < -1) then + return 0; + end if; + arg_s := to_s(resize (arg => arg, + left_index => arg_s'high, + right_index => 0, + round_style => round_style, + overflow_style => overflow_style)); + return to_integer (arg_s); + end function to_integer; + + function to_01 ( + s : ufixed; -- ufixed point input + constant XMAP : STD_LOGIC := '0') -- Map x to + return ufixed is + variable result : ufixed (s'range); -- result + begin + for i in s'range loop + case s(i) is + when '0' | 'L' => result(i) := '0'; + when '1' | 'H' => result(i) := '1'; + when others => result(i) := XMAP; + end case; + end loop; + return result; + end function to_01; + + function to_01 ( + s : sfixed; -- ufixed point input + constant XMAP : STD_LOGIC := '0') -- Map x to + return sfixed is + variable result : sfixed (s'range); + begin + for i in s'range loop + case s(i) is + when '0' | 'L' => result(i) := '0'; + when '1' | 'H' => result(i) := '1'; + when others => result(i) := XMAP; + end case; + end loop; + return result; + end function to_01; + + function Is_X ( + arg : ufixed) + return BOOLEAN is + variable argslv : STD_LOGIC_VECTOR (arg'length-1 downto 0); -- slv + begin + argslv := to_slv(arg); + return Is_X(argslv); + end function Is_X; + + function Is_X ( + arg : sfixed) + return BOOLEAN is + variable argslv : STD_LOGIC_VECTOR (arg'length-1 downto 0); -- slv + begin + argslv := to_slv(arg); + return Is_X(argslv); + end function Is_X; + + function To_X01 ( + arg : ufixed) + return ufixed is + begin + return to_ufixed (To_X01(to_slv(arg)), arg'high, arg'low); + end function To_X01; + + function to_X01 ( + arg : sfixed) + return sfixed is + begin + return to_sfixed (To_X01(to_slv(arg)), arg'high, arg'low); + end function To_X01; + + function To_X01Z ( + arg : ufixed) + return ufixed is + begin + return to_ufixed (To_X01Z(to_slv(arg)), arg'high, arg'low); + end function To_X01Z; + + function to_X01Z ( + arg : sfixed) + return sfixed is + begin + return to_sfixed (To_X01Z(to_slv(arg)), arg'high, arg'low); + end function To_X01Z; + + function To_UX01 ( + arg : ufixed) + return ufixed is + begin + return to_ufixed (To_UX01(to_slv(arg)), arg'high, arg'low); + end function To_UX01; + + function to_UX01 ( + arg : sfixed) + return sfixed is + begin + return to_sfixed (To_UX01(to_slv(arg)), arg'high, arg'low); + end function To_UX01; + + + function resize ( + arg : ufixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed is + constant arghigh : INTEGER := maximum (arg'high, arg'low); + constant arglow : INTEGER := mine (arg'high, arg'low); + variable invec : ufixed (arghigh downto arglow); + variable result : ufixed(left_index downto right_index) := + (others => '0'); + variable needs_rounding : BOOLEAN := false; + begin -- resize + if (arg'length < 1) or (result'length < 1) then + return NAUF; + elsif (invec'length < 1) then + return result; -- string literal value + else + invec := cleanvec(arg); + if (right_index > arghigh) then -- return top zeros + needs_rounding := (round_style = fixed_round) and + (right_index = arghigh+1); + elsif (left_index < arglow) then -- return overflow + if (overflow_style = fixed_saturate) and + (or_reducex(to_slv(invec)) = '1') then + result := saturate (result'high, result'low); -- saturate + end if; + elsif (arghigh > left_index) then + -- wrap or saturate? + if (overflow_style and + or_reducex(to_slv(invec(arghigh downto left_index+1))) = '1') + then + result := saturate (result'high, result'low); -- saturate + else + if (arglow >= right_index) then + result (left_index downto arglow) := + invec(left_index downto arglow); + else + result (left_index downto right_index) := + invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + end if; + else -- arghigh <= integer width + if (arglow >= right_index) then + result (arghigh downto arglow) := invec; + else + result (arghigh downto right_index) := + invec (arghigh downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + end if; + -- Round result + if needs_rounding then + result := round_fixed (arg => result, + remainder => invec (right_index-1 + downto arglow), + overflow_style => overflow_style); + end if; + return result; + end if; + end function resize; + + function resize ( + arg : sfixed; -- input + constant left_index : INTEGER; -- integer portion + constant right_index : INTEGER; -- size of fraction + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return sfixed is + constant arghigh : INTEGER := maximum (arg'high, arg'low); + constant arglow : INTEGER := mine (arg'high, arg'low); + variable invec : sfixed (arghigh downto arglow); + variable result : sfixed(left_index downto right_index) := + (others => '0'); + variable reduced : STD_ULOGIC; + variable needs_rounding : BOOLEAN := false; -- rounding + begin -- resize + if (arg'length < 1) or (result'length < 1) then + return NASF; + elsif (invec'length < 1) then + return result; -- string literal value + else + invec := cleanvec(arg); + if (right_index > arghigh) then -- return top zeros + if (arg'low /= INTEGER'low) then -- check for a literal + result := (others => arg(arghigh)); -- sign extend + end if; + needs_rounding := (round_style = fixed_round) and + (right_index = arghigh+1); + elsif (left_index < arglow) then -- return overflow + if (overflow_style) then + reduced := or_reducex(to_slv(invec)); + if (reduced = '1') then + if (invec(arghigh) = '0') then + -- saturate POSITIVE + result := saturate (result'high, result'low); + else + -- saturate negative + result := not saturate (result'high, result'low); + end if; + -- else return 0 (input was 0) + end if; + -- else return 0 (wrap) + end if; + elsif (arghigh > left_index) then + if (invec(arghigh) = '0') then + reduced := or_reducex(to_slv(invec(arghigh-1 downto + left_index))); + if overflow_style and reduced = '1' then + -- saturate positive + result := saturate (result'high, result'low); + else + if (right_index > arglow) then + result := invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); + else + result (left_index downto arglow) := + invec (left_index downto arglow); + end if; + end if; + else + reduced := and_reducex(to_slv(invec(arghigh-1 downto + left_index))); + if overflow_style and reduced = '0' then + result := not saturate (result'high, result'low); + else + if (right_index > arglow) then + result := invec (left_index downto right_index); + needs_rounding := (round_style = fixed_round); + else + result (left_index downto arglow) := + invec (left_index downto arglow); + end if; + end if; + end if; + else -- arghigh <= integer width + if (arglow >= right_index) then + result (arghigh downto arglow) := invec; + else + result (arghigh downto right_index) := + invec (arghigh downto right_index); + needs_rounding := (round_style = fixed_round); -- round + end if; + if (left_index > arghigh) then -- sign extend + result(left_index downto arghigh+1) := (others => invec(arghigh)); + end if; + end if; + -- Round result + if (needs_rounding) then + result := round_fixed (arg => result, + remainder => invec (right_index-1 + downto arglow), + overflow_style => overflow_style); + end if; + return result; + end if; + end function resize; + + -- size_res functions + -- These functions compute the size from a passed variable named "size_res" + -- The only part of this variable used it it's size, it is never passed + -- to a lower level routine. + function to_ufixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : ufixed) -- for size only + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : STD_LOGIC_VECTOR; -- shifted vector + size_res : sfixed) -- for size only + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : ufixed) -- for size only + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => to_stdlogicvector(arg), + left_index => size_res'high, + right_index => size_res'low); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : STD_ULOGIC_VECTOR; -- shifted vector + size_res : sfixed) -- for size only + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => to_stdlogicvector(arg), + left_index => size_res'high, + right_index => size_res'low); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : NATURAL; -- integer + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : INTEGER; -- integer + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : REAL; -- real + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + guard_bits => guard_bits, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : REAL; -- real + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style; -- turn on rounding by default + constant guard_bits : NATURAL := fixed_guard_bits) -- # of guard bits + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + guard_bits => guard_bits, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function to_ufixed ( + arg : UNSIGNED; -- unsigned + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_ufixed; + + function to_sfixed ( + arg : SIGNED; -- signed + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate by default + constant round_style : BOOLEAN := fixed_round_style) -- turn on rounding by default + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function to_sfixed; + + function resize ( + arg : ufixed; -- input + size_res : ufixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := resize (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function resize; + + function resize ( + arg : sfixed; -- input + size_res : sfixed; -- for size only + constant overflow_style : BOOLEAN := fixed_overflow_style; -- overflow + constant round_style : BOOLEAN := fixed_round_style) -- rounding + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := resize (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style); + return result; + end if; + end function resize; + + -- Overloaded functions + function "+" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l + + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "+"; + + function "+" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + + r); + end function "+"; + + function "+" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l + + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "+"; + + function "+" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + + r); + end function "+"; + + -- Overloaded functions + function "-" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l - + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "-"; + + function "-" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + - r); + end function "-"; + + function "-" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l - + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "-"; + + function "-" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + - r); + end function "-"; + + -- Overloaded functions + function "*" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l * + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "*"; + + function "*" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + * r); + end function "*"; + + function "*" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l * + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "*"; + + function "*" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + * r); + end function "*"; + + -- Overloaded functions + function "/" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l / + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "/"; + + function "/" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + / r); + end function "/"; + + function "/" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l / + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "/"; + + function "/" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + / r); + end function "/"; + + -- Overloaded functions + function "rem" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l rem + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "rem"; + + function "rem" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + rem r); + end function "rem"; + + function "rem" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l rem + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "rem"; + + function "rem" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + rem r); + end function "rem"; + + function "mod" ( + l : ufixed; -- fixed point input + r : REAL) + return ufixed is + begin + return (l mod + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "mod"; + + function "mod" ( + l : REAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + mod r); + end function "mod"; + + function "mod" ( + l : sfixed; -- fixed point input + r : REAL) + return sfixed is + begin + return (l mod + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "mod"; + + function "mod" ( + l : REAL; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + mod r); + end function "mod"; + + -- Overloaded functions for integers + function "+" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); -- rounding not needed + end function "+"; + + function "+" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + + r); + end function "+"; + + function "+" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "+"; + + function "+" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + + r); + end function "+"; + + -- Overloaded functions + function "-" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l - to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "-"; + + function "-" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + - r); + end function "-"; + + function "-" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l - to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "-"; + + function "-" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + - r); + end function "-"; + + -- Overloaded functions + function "*" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l * to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "*"; + + function "*" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + * r); + end function "*"; + + function "*" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l * to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "*"; + + function "*" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + * r); + end function "*"; + + -- Overloaded functions + function "/" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l / to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "/"; + + function "/" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + / r); + end function "/"; + + function "/" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l / to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "/"; + + function "/" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + / r); + end function "/"; + + -- Overloaded functions + function "rem" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l rem to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "rem"; + + function "rem" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + rem r); + end function "rem"; + + function "rem" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l rem to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "rem"; + + function "rem" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + rem r); + end function "rem"; + + function "mod" ( + l : ufixed; -- fixed point input + r : NATURAL) + return ufixed is + begin + return (l mod to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "mod"; + + function "mod" ( + l : NATURAL; + r : ufixed) -- fixed point input + return ufixed is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + mod r); + end function "mod"; + + function "mod" ( + l : sfixed; -- fixed point input + r : INTEGER) + return sfixed is + begin + return (l mod to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "mod"; + + function "mod" ( + l : INTEGER; + r : sfixed) -- fixed point input + return sfixed is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + mod r); + end function "mod"; + + -- overloaded compare functions + function "=" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l = to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "="; + + function "/=" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l /= to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "/="; + + function ">=" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l >= to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function ">="; + + function "<=" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l <= to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "<="; + + function ">" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l > to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function ">"; + + function "<" ( + l : ufixed; + r : NATURAL) -- fixed point input + return BOOLEAN is + begin + return (l < to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "<"; + + function "=" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + = r); + end function "="; + + function "/=" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + /= r); + end function "/="; + + function ">=" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + >= r); + end function ">="; + + function "<=" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + <= r); + end function "<="; + + function ">" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + > r); + end function ">"; + + function "<" ( + l : NATURAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + < r); + end function "<"; + + function "=" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l = + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "="; + + function "/=" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l /= + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "/="; + + function ">=" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l >= + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function ">="; + + function "<=" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l <= + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "<="; + + function ">" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l > + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function ">"; + + function "<" ( + l : ufixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l < + to_ufixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "<"; + + function "=" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + = r); + end function "="; + + function "/=" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + /= r); + end function "/="; + + function ">=" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + >= r); + end function ">="; + + function "<=" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + <= r); + end function "<="; + + function ">" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + > r); + end function ">"; + + function "<" ( + l : REAL; + r : ufixed) -- fixed point input + return BOOLEAN is + begin + return (to_ufixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + < r); + end function "<"; + + function "=" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l = to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "="; + + function "/=" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l /= to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "/="; + + function ">=" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l >= to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function ">="; + + function "<=" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l <= to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "<="; + + function ">" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l > to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function ">"; + + function "<" ( + l : sfixed; + r : INTEGER) -- fixed point input + return BOOLEAN is + begin + return (l < to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style)); + end function "<"; + + function "=" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + = r); + end function "="; + + function "/=" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + /= r); + end function "/="; + + function ">=" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + >= r); + end function ">="; + + function "<=" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + <= r); + end function "<="; + + function ">" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + > r); + end function ">"; + + function "<" ( + l : INTEGER; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style) + < r); + end function "<"; + + function "=" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l = + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "="; + + function "/=" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l /= + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "/="; + + function ">=" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l >= + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function ">="; + + function "<=" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l <= + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "<="; + + function ">" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l > + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function ">"; + + function "<" ( + l : sfixed; + r : REAL) -- fixed point input + return BOOLEAN is + begin + return (l < + to_sfixed (arg => r, + left_index => l'high, + right_index => l'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits)); + end function "<"; + + function "=" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + = r); + end function "="; + + function "/=" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + /= r); + end function "/="; + + function ">=" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + >= r); + end function ">="; + + function "<=" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + <= r); + end function "<="; + + function ">" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + > r); + end function ">"; + + function "<" ( + l : REAL; + r : sfixed) -- fixed point input + return BOOLEAN is + begin + return (to_sfixed (arg => l, + left_index => r'high, + right_index => r'low, + overflow_style => fixed_overflow_style, + round_style => fixed_round_style, + guard_bits => fixed_guard_bits) + < r); + end function "<"; + + -- rtl_synthesis off + -- synthesis translate_off + -- copied from std_logic_textio + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER; + type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus; + + constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9 : MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus : MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error); + constant NBSP : CHARACTER := CHARACTER'val(160); -- space character + constant NUS : STRING(2 to 1) := (others => ' '); + + -- purpose: writes fixed point into a line + procedure write ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable sindx : INTEGER; + begin -- function write Example: 0011.1100 + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx +1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx +1; + end loop; + write(l, s, justified, field); + end procedure write; + + -- purpose: writes fixed point into a line + procedure write ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + variable s : STRING(1 to value'length +1); + variable sindx : INTEGER; + begin -- function write Example: 0011.1100 + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx +1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx +1; + end loop; + write(l, s, justified, field); + end procedure write; + + procedure READ(L : inout LINE; + VALUE : out ufixed) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable s : STRING(1 to value'length-1); + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + begin -- READ + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + i := value'high; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + report "FIXED_GENERIC_PKG.READ(ufixed) " + & "Error: end of string encountered" + severity error; + return; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + assert i = value'low + report "FIXED_GENERIC_PKG.READ(ufixed) " + & "Warning: Value truncated " severity warning; + return; + elsif c = '.' then -- separator, ignore + assert (i = -1) + report "FIXED_GENERIC_PKG.READ(ufixed) " + & "Warning: Decimal point does not match number format " + severity warning; + elsif (char_to_MVL9plus(c) = error) then + report "FIXED_GENERIC_PKG.READ(ufixed) " + & "Error: Character '" & c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable i : INTEGER; -- index variable + variable readOk : BOOLEAN; + begin -- READ + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + i := value'high; + good := true; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + good := false; + return; + elsif c = ' ' or c = NBSP or c = HT then -- reading done + good := false; + return; + elsif c = '.' then -- separator, ignore + good := (i = -1); + elsif (char_to_MVL9plus(c) = error) then + good := false; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out sfixed) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + begin -- READ + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + i := value'high; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + report "FIXED_GENERIC_PKG.READ(sfixed) " + & "Error end of string encountered" + severity error; + return; + elsif c = ' ' or c = NBSP or c = HT then -- reading done. + assert i = value'low + report "FIXED_GENERIC_PKG.READ(sfixed) " + & "Warning: Value truncated " severity warning; + return; + elsif c = '.' then -- separator, ignore + assert (i = -1) + report "FIXED_GENERIC_PKG.READ(sfixed) " + & "Warning: Decimal point does not match number format " + severity warning; + elsif (char_to_MVL9plus(c) = error) then + report "FIXED_GENERIC_PKG.READ(sfixed) " + & "Error: Character '" & c & "' read, expected STD_ULOGIC literal." + severity error; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + procedure READ(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN) is + -- Possible data: 00000.0000000 + -- 000000000000 + variable c : CHARACTER; + variable i : INTEGER; -- index variable + variable readOk : BOOLEAN; + begin -- READ + VALUE (VALUE'range) := (others => 'U'); + loop -- skip white space + read(l, c, readOk); + exit when (readOk = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + i := value'high; + good := true; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + good := false; + return; + elsif c = ' ' or c = NBSP or c = HT then -- reading done + good := false; + return; + elsif c = '.' then -- separator, ignore + good := (i = -1); + elsif (char_to_MVL9plus(c) = error) then + good := false; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + -- octal read and write + procedure owrite ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_ostring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure owrite; + + procedure owrite ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_ostring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure owrite; + + procedure Char2TriBits (C : CHARACTER; + RESULT : out STD_LOGIC_VECTOR(2 downto 0); + GOOD : out BOOLEAN; + ISSUE_ERROR : in BOOLEAN) is + begin + case c is + when '0' => result := o"0"; good := true; + when '1' => result := o"1"; good := true; + when '2' => result := o"2"; good := true; + when '3' => result := o"3"; good := true; + when '4' => result := o"4"; good := true; + when '5' => result := o"5"; good := true; + when '6' => result := o"6"; good := true; + when '7' => result := o"7"; good := true; + when 'Z' => result := "ZZZ"; good := true; + when 'X' => result := "XXX"; good := true; + when others => + assert not ISSUE_ERROR + report + "FIXED_GENERIC_PKG.OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)." + severity error; + result := "UUU"; + good := false; + end case; + end procedure Char2TriBits; + + -- Note that for Octal and Hex read, you can not start with a ".", + -- the read is for numbers formatted "A.BC". These routines go to + -- the nearest bounds, so "F.E" will fit into an sfixed (2 downto -3). + procedure OREAD(L : inout LINE; + VALUE : out ufixed) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + report "FIXED_GENERIC_PKG.OREAD(ufixed): " + & "Error end of string encountered" + severity error; + return; + else + Char2triBits(c, nybble, igood, true); + i := hbv-lbv - 3; -- Top - 3 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood = false then + report "FIXED_GENERIC_PKG.OREAD(ufixed): " + & "Error end of string encountered" + severity error; + elsif (c = '.') then + if (i + 1 /= -lbv) then + igood := false; + report "FIXED_GENERIC_PKG.OREAD(ufixed): " + & "encountered ""."" at wrong index" + severity error; + end if; + else + Char2TriBits(c, nybble, igood, true); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end loop; + if igood then -- We did not get another error + assert (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') + report "FIXED_GENERIC_PKG.OREAD(ufixed): Vector truncated." + severity error; + if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "FIXED_GENERIC_PKG.OREAD(ufixed): Vector truncated" + severity warning; + end if; + end if; + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + return; + else + Char2triBits(c, nybble, igood, false); + i := hbv-lbv - 3; -- Top - 3 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood then + if (c = '.') then + igood := igood and (i + 1 = -lbv); + else + Char2TriBits(c, nybble, igood, false); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end if; + end loop; + good := igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0'); + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out sfixed) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + report "FIXED_GENERIC_PKG.OREAD(sfixed): " + & "Error end of string encountered" + severity error; + return; + else + Char2triBits(c, nybble, igood, true); + i := hbv-lbv - 3; -- Top - 3 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood = false then + report "FIXED_GENERIC_PKG.OREAD(sfixed): " + & "Error end of string encountered" + severity error; + elsif (c = '.') then + if (i + 1 /= -lbv) then + igood := false; + report "FIXED_GENERIC_PKG.OREAD(sfixed): " + & "encountered ""."" at wrong index" + severity error; + end if; + else + Char2TriBits(c, nybble, igood, true); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end loop; + if igood then -- We did not get another error + assert (i = -1) and -- We read everything + ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')) + report "FIXED_GENERIC_PKG.OREAD(sfixed): Vector truncated." + severity error; + if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "FIXED_GENERIC_PKG.OREAD(sfixed): Vector truncated" + severity warning; + end if; + end if; + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure OREAD; + + procedure OREAD(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(3, (VALUE'high+1))+2)/3)*3)-1; + constant lbv : INTEGER := ((mine(-3, VALUE'low)-2)/3)*3; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + return; + else + Char2triBits(c, nybble, igood, false); + i := hbv-lbv - 3; -- Top - 3 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood then + if (c = '.') then + igood := igood and (i + 1 = -lbv); + else + Char2TriBits(c, nybble, igood, false); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end if; + end loop; + good := igood -- We did not get another error + and (i = -1) -- We read everything + and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')); + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure OREAD; + + -- hex read and write + procedure hwrite ( + L : inout LINE; -- input line + VALUE : in ufixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_hstring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure hwrite; + + -- purpose: writes fixed point into a line + procedure hwrite ( + L : inout LINE; -- input line + VALUE : in sfixed; -- fixed point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + begin -- Example 03.30 + write (L => L, + VALUE => to_hstring (VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure hwrite; + + -- Hex Read and Write procedures for STD_ULOGIC_VECTOR. + -- Modified from the original to be more forgiving. + + procedure Char2QuadBits (C : CHARACTER; + RESULT : out STD_LOGIC_VECTOR(3 downto 0); + GOOD : out BOOLEAN; + ISSUE_ERROR : in BOOLEAN) is + begin + case c is + when '0' => result := x"0"; good := true; + when '1' => result := x"1"; good := true; + when '2' => result := x"2"; good := true; + when '3' => result := x"3"; good := true; + when '4' => result := x"4"; good := true; + when '5' => result := x"5"; good := true; + when '6' => result := x"6"; good := true; + when '7' => result := x"7"; good := true; + when '8' => result := x"8"; good := true; + when '9' => result := x"9"; good := true; + when 'A' | 'a' => result := x"A"; good := true; + when 'B' | 'b' => result := x"B"; good := true; + when 'C' | 'c' => result := x"C"; good := true; + when 'D' | 'd' => result := x"D"; good := true; + when 'E' | 'e' => result := x"E"; good := true; + when 'F' | 'f' => result := x"F"; good := true; + when 'Z' => result := "ZZZZ"; good := true; + when 'X' => result := "XXXX"; good := true; + when others => + assert not ISSUE_ERROR + report + "FIXED_GENERIC_PKG.HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)." + severity error; + result := "UUUU"; + good := false; + end case; + end procedure Char2QuadBits; + + procedure HREAD(L : inout LINE; + VALUE : out ufixed) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + report "FIXED_GENERIC_PKG.HREAD(ufixed): " + & "Error end of string encountered" + severity error; + return; + else + Char2QuadBits(c, nybble, igood, true); + i := hbv-lbv - 4; -- Top - 4 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood = false then + report "FIXED_GENERIC_PKG.HREAD(ufixed): " + & "Error end of string encountered" + severity error; + elsif (c = '.') then + if (i + 1 /= -lbv) then + igood := false; + report "FIXED_GENERIC_PKG.HREAD(ufixed): " + & "encountered ""."" at wrong index" + severity error; + end if; + else + Char2QuadBits(c, nybble, igood, true); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end loop; + if igood then -- We did not get another error + assert (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') + report "FIXED_GENERIC_PKG.HREAD(ufixed): Vector truncated." + severity error; + if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "FIXED_GENERIC_PKG.HREAD(ufixed): Vector truncated" + severity warning; + end if; + end if; + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out ufixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : ufixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + return; + else + Char2QuadBits(c, nybble, igood, false); + i := hbv-lbv - 4; -- Top - 4 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood then + if (c = '.') then + igood := igood and (i + 1 = -lbv); + else + Char2QuadBits(c, nybble, igood, false); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end if; + end loop; + good := igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0'); + valuex := to_ufixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out sfixed) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + report "FIXED_GENERIC_PKG.HREAD(sfixed): " + & "Error end of string encountered" + severity error; + return; + else + Char2QuadBits(c, nybble, igood, true); + i := hbv-lbv - 4; -- Top - 4 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood = false then + report "FIXED_GENERIC_PKG.HREAD(sfixed): " + & "Error end of string encountered" + severity error; + elsif (c = '.') then + if (i + 1 /= -lbv) then + igood := false; + report "FIXED_GENERIC_PKG.HREAD(sfixed): " + & "encountered ""."" at wrong index" + severity error; + end if; + else + Char2QuadBits(c, nybble, igood, true); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end loop; + if igood then -- We did not get another error + assert (i = -1) -- We read everything + and ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')) + report "FIXED_GENERIC_PKG.HREAD(sfixed): Vector truncated." + severity error; + if (or_reducex(slv(VALUE'low-lbv-1 downto 0)) = '1') then + assert NO_WARNING + report "FIXED_GENERIC_PKG.HREAD(sfixed): Vector truncated" + severity warning; + end if; + end if; + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure HREAD; + + procedure HREAD(L : inout LINE; + VALUE : out sfixed; + GOOD : out BOOLEAN) is + constant hbv : INTEGER := (((maximum(4, (VALUE'high+1))+3)/4)*4)-1; + constant lbv : INTEGER := ((mine(-4, VALUE'low)-3)/4)*4; + variable slv : STD_LOGIC_VECTOR (hbv-lbv downto 0); -- high bits + variable c : CHARACTER; -- to read the "." + variable valuex : sfixed (hbv downto lbv); + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + VALUE (VALUE'range) := (others => 'U'); -- initialize to a "U" + loop -- skip white space + read(L, c, igood); + exit when (igood = false) or ((c /= ' ') and (c /= NBSP) and (c /= HT)); + end loop; + if igood = false then + return; + else + Char2QuadBits(c, nybble, igood, false); + i := hbv-lbv - 4; -- Top - 4 + slv (hbv-lbv downto i+1) := nybble; + end if; + while (i /= -1) and igood and L.all'length /= 0 loop + read (L, c, igood); + if igood then + if (c = '.') then + igood := igood and (i + 1 = -lbv); + else + Char2QuadBits(c, nybble, igood, false); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end if; + end loop; + good := igood and -- We did not get another error + (i = -1) and -- We read everything + ((slv(VALUE'high-lbv) = '0' and -- sign bits = extra bits + or_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '0') or + (slv(VALUE'high-lbv) = '1' and + and_reducex(slv(hbv-lbv downto VALUE'high+1-lbv)) = '1')); + valuex := to_sfixed (slv, hbv, lbv); + VALUE := valuex (VALUE'range); + end procedure HREAD; + + ----------------------------------------------------------------------------- + -- %%% Remove the following 3 functions. They are a duplicate needed for + -- testing + ----------------------------------------------------------------------------- + -- purpose: Justify a string to the right + function justify ( + value : STRING; + justified : SIDE := right; + field : width := 0) + return STRING is + constant VAL_LEN : INTEGER := value'length; + variable result : STRING (1 to field) := (others => ' '); + begin -- function justify + -- return value if field is too small + if VAL_LEN >= field then + return value; + end if; + if justified = left then + result(1 to VAL_LEN) := value; + elsif justified = right then + result(field - VAL_LEN + 1 to field) := value; + end if; + return result; + end function justify; + + function to_ostring ( + value : STD_LOGIC_VECTOR; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := (value'length+2)/3; + variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - value'length) - 1); + variable ivalue : STD_LOGIC_VECTOR(0 to ne*3 - 1); + variable result : STRING(1 to ne); + variable tri : STD_LOGIC_VECTOR(0 to 2); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + tri := To_X01Z(ivalue(3*i to 3*i+2)); + case tri is + when o"0" => result(i+1) := '0'; + when o"1" => result(i+1) := '1'; + when o"2" => result(i+1) := '2'; + when o"3" => result(i+1) := '3'; + when o"4" => result(i+1) := '4'; + when o"5" => result(i+1) := '5'; + when o"6" => result(i+1) := '6'; + when o"7" => result(i+1) := '7'; + when "ZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_ostring; + ------------------------------------------------------------------- + function to_hstring ( + value : STD_LOGIC_VECTOR; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := (value'length+3)/4; + variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - value'length) - 1); + variable ivalue : STD_LOGIC_VECTOR(0 to ne*4 - 1); + variable result : STRING(1 to ne); + variable quad : STD_LOGIC_VECTOR(0 to 3); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + quad := To_X01Z(ivalue(4*i to 4*i+3)); + case quad is + when x"0" => result(i+1) := '0'; + when x"1" => result(i+1) := '1'; + when x"2" => result(i+1) := '2'; + when x"3" => result(i+1) := '3'; + when x"4" => result(i+1) := '4'; + when x"5" => result(i+1) := '5'; + when x"6" => result(i+1) := '6'; + when x"7" => result(i+1) := '7'; + when x"8" => result(i+1) := '8'; + when x"9" => result(i+1) := '9'; + when x"A" => result(i+1) := 'A'; + when x"B" => result(i+1) := 'B'; + when x"C" => result(i+1) := 'C'; + when x"D" => result(i+1) := 'D'; + when x"E" => result(i+1) := 'E'; + when x"F" => result(i+1) := 'F'; + when "ZZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_hstring; + -- %%% End remove here + + function to_string ( + value : ufixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable sindx : INTEGER; + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_string (resize (value, 0, value'low), justified, field); + elsif value'low > 0 then + return to_string (resize (value, value'high, -1), justified, field); + else + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx +1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx +1; + end loop; + return justify(s, justified, field); + end if; + end if; + end function to_string; + + function to_string ( + value : sfixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + variable s : STRING(1 to value'length +1) := (others => ' '); + variable sindx : INTEGER; + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_string (resize (value, 0, value'low), justified, field); + elsif value'low > 0 then + return to_string (resize (value, value'high, -1), justified, field); + else + sindx := 1; + for i in value'high downto value'low loop + if i = -1 then + s(sindx) := '.'; + sindx := sindx +1; + end if; + s(sindx) := MVL9_to_char(STD_ULOGIC(value(i))); + sindx := sindx +1; + end loop; + return justify(s, justified, field); + end if; + end if; + end function to_string; + + function to_ostring ( + value : ufixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant lne : INTEGER := (-VALUE'low+2)/3; + constant lpad : STD_LOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1) := + (others => '0'); + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_ostring (resize (value, 2, value'low), justified, field); + elsif value'low > 0 then + return to_ostring (resize (value, value'high, -3), justified, field); + else + slv := to_slv (value); + return justify(to_ostring(slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_ostring(slv(slv'high-VALUE'high-1 downto 0)&lpad), + justified, field); + end if; + end if; + end function to_ostring; + + function to_hstring ( + value : ufixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant lne : INTEGER := (-VALUE'low+3)/4; + constant lpad : STD_LOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1) := + (others => '0'); + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + if value'high < 0 then + return to_hstring (resize (value, 3, value'low), justified, field); + elsif value'low > 0 then + return to_hstring (resize (value, value'high, -4), justified, field); + else + slv := to_slv (value); + return justify(to_hstring(slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_hstring(slv(slv'high-VALUE'high-1 downto 0)&lpad), + justified, field); + end if; + end if; + end function to_hstring; + + function to_ostring ( + value : sfixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := ((value'high+1)+2)/3; + variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - (value'high+1)) - 1); + constant lne : INTEGER := (-VALUE'low+2)/3; + constant lpad : STD_LOGIC_VECTOR (0 to (lne*3 + VALUE'low) -1) := + (others => '0'); + variable slv : STD_LOGIC_VECTOR (VALUE'high - VALUE'low downto 0); + begin + if value'length < 1 then + return NUS; + else + pad := (others => value(value'high)); + if value'high < 0 then + return to_ostring (resize (value, 2, value'low), justified, field); + elsif value'low > 0 then + return to_ostring (resize (value, value'high, -3), justified, field); + else + slv := to_slv (value); + return justify(to_ostring(pad + & slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_ostring(slv(slv'high-VALUE'high-1 downto 0) + & lpad), + justified, field); + end if; + end if; + end function to_ostring; + + function to_hstring ( + value : sfixed; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := ((value'high+1)+3)/4; + variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - (value'high+1)) - 1); + constant lne : INTEGER := (-VALUE'low+3)/4; + constant lpad : STD_LOGIC_VECTOR (0 to (lne*4 + VALUE'low) -1) := + (others => '0'); + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + if value'length < 1 then + return NUS; + else + pad := (others => value(value'high)); + if value'high < 0 then + return to_hstring (resize (value, 3, value'low), justified, field); + elsif value'low > 0 then + return to_hstring (resize (value, value'high, -4), justified, field); + else + slv := to_slv (value); + return justify(to_hstring(pad&slv(slv'high downto slv'high-VALUE'high)) + & "." + & to_hstring(slv(slv'high-VALUE'high-1 downto 0)&lpad), + justified, field); + end if; + end if; + end function to_hstring; + + -- From string functions allow you to convert a string into a fixed + -- point number. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100", uf1'high, uf1'low); -- 6.5 + -- The "." is optional in this syntax, however it exist and is + -- in the wrong location an error is produced. Overflow will + -- result in saturation. + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + -- Octal and hex conversions work as follows: + -- uf1 <= from_hstring ("6.8", 3, -3); -- 6.5 (bottom zeros dropped) + -- uf1 <= from_ostring ("06.4", 3, -3); -- 6.5 (top zeros dropped) + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return ufixed is + variable result : ufixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + constant left_index : INTEGER; + constant right_index : INTEGER) + return sfixed is + variable result : sfixed (left_index downto right_index); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + -- Same as above, "size_res" is used for it's range only. + function from_string ( + bstring : STRING; -- binary string + size_res : ufixed) + return ufixed is + variable result : ufixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : ufixed) + return ufixed is + variable result : ufixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : ufixed) + return ufixed is + variable result : ufixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + size_res : sfixed) + return sfixed is + variable result : sfixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : sfixed) + return sfixed is + variable result : sfixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : sfixed) + return sfixed is + variable result : sfixed (size_res'high downto size_res'low); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + return result; + end function from_hstring; + + -- purpose: find a dot in a string, return -1 if no dot (internal function) + function finddot ( + arg : STRING) + return INTEGER is + alias xarg : STRING (arg'length downto 1) is arg; -- make it a downto + begin + for i in xarg'reverse_range loop + if (xarg(i) = '.') then + return i-1; + end if; + end loop; + return -1; + end function finddot; + + -- Direct converstion functions. Example: + -- signal uf1 : ufixed (3 downto -3); + -- uf1 <= from_string ("0110.100"); -- 6.5 + -- In this case the "." is not optional, and the size of + -- the output must match exactly. + function from_string ( + bstring : STRING) -- binary string + return ufixed is + variable result : ufixed (bstring'length-2 downto 0); + variable result_nodot : ufixed (bstring'length-1 downto 0); + variable bstring_nodot : STRING (1 to bstring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(bstring); + if (dot = -1) then + L := new STRING'(bstring); + read (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + deallocate (L); + return result_nodot; + else + j := 1; + for i in 1 to bstring'high loop + if (bstring(i) /= '.') then + bstring_nodot(j) := bstring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(bstring_nodot); + read (L, result, good); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + deallocate (L); + return to_ufixed(to_slv(result), bstring'length-dot-2, -dot); + end if; + end function from_string; + + -- Direct octal and hex converstion functions. In this case + -- the string lengths must match. Example: + -- signal sf1 := sfixed (5 downto -3); + -- sf1 <= from_ostring ("71.4") -- -6.5 + function from_ostring ( + ostring : STRING) -- Octal string + return ufixed is + variable result : STD_LOGIC_VECTOR((ostring'length-1)*3-1 downto 0); + variable result_nodot : STD_LOGIC_VECTOR((ostring'length)*3-1 downto 0); + variable ostring_nodot : STRING (1 to ostring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(ostring); + if (dot = -1) then + L := new STRING'(ostring); + oread (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + deallocate (L); + return to_ufixed(UNSIGNED(result_nodot)); + else + j := 1; + for i in 1 to ostring'high loop + if (ostring(i) /= '.') then + ostring_nodot(j) := ostring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(ostring_nodot); + oread (L, result, good); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + deallocate (L); + return to_ufixed(result, (ostring'length-1-dot)*3-1, -dot*3); + end if; + end function from_ostring; + + function from_hstring ( + hstring : STRING) -- hex string + return ufixed is + variable result : STD_LOGIC_VECTOR((hstring'length-1)*4-1 downto 0); + variable result_nodot : STD_LOGIC_VECTOR((hstring'length)*4-1 downto 0); + variable hstring_nodot : STRING (1 to hstring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(hstring); + if (dot = -1) then + L := new STRING'(hstring); + hread (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + deallocate (L); + return to_ufixed(UNSIGNED(result_nodot)); + else + j := 1; + for i in 1 to hstring'high loop + if (hstring(i) /= '.') then + hstring_nodot(j) := hstring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(hstring_nodot); + hread (L, result, good); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + deallocate (L); + return to_ufixed(result, (hstring'length-1-dot)*4-1, -dot*4); + end if; + end function from_hstring; + + function from_string ( + bstring : STRING) -- binary string + return sfixed is + variable result : sfixed (bstring'length-2 downto 0); + variable result_nodot : sfixed (bstring'length-1 downto 0); + variable bstring_nodot : STRING (1 to bstring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(bstring); + if (dot = -1) then + L := new STRING'(bstring); + read (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + deallocate (L); + return result_nodot; + else + j := 1; + for i in 1 to bstring'high loop + if (bstring(i) /= '.') then + bstring_nodot(j) := bstring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(bstring_nodot); + read (L, result, good); + assert (good) + report "fixed_generic_pkg.from_string: Bad string "& bstring severity error; + deallocate (L); + return to_sfixed(to_slv(result), bstring'length-dot-2, -dot); + end if; + end function from_string; + + function from_ostring ( + ostring : STRING) -- Octal string + return sfixed is + variable result : STD_LOGIC_VECTOR((ostring'length-1)*3-1 downto 0); + variable result_nodot : STD_LOGIC_VECTOR((ostring'length)*3-1 downto 0); + variable ostring_nodot : STRING (1 to ostring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(ostring); + if (dot = -1) then + L := new STRING'(ostring); + oread (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + deallocate (L); + return to_sfixed(SIGNED(result_nodot)); + else + j := 1; + for i in 1 to ostring'high loop + if (ostring(i) /= '.') then + ostring_nodot(j) := ostring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(ostring_nodot); + oread (L, result, good); + assert (good) + report "fixed_generic_pkg.from_ostring: Bad string "& ostring severity error; + deallocate (L); + return to_sfixed(result, (ostring'length-1-dot)*3-1, -dot*3); + end if; + end function from_ostring; + + function from_hstring ( + hstring : STRING) -- hex string + return sfixed is + variable result : STD_LOGIC_VECTOR((hstring'length-1)*4-1 downto 0); + variable result_nodot : STD_LOGIC_VECTOR((hstring'length)*4-1 downto 0); + variable hstring_nodot : STRING (1 to hstring'length-1); + variable L : LINE; + variable good : BOOLEAN; + variable dot, i, j : INTEGER; + begin + dot := finddot(hstring); + if (dot = -1) then + L := new STRING'(hstring); + hread (L, result_nodot, good); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + deallocate (L); + return sfixed(SIGNED(result_nodot)); + else + j := 1; + for i in 1 to hstring'high loop + if (hstring(i) /= '.') then + hstring_nodot(j) := hstring(i); -- get rid of the dot. + j := j + 1; + end if; + end loop; + L := new STRING'(hstring_nodot); + hread (L, result, good); + assert (good) + report "fixed_generic_pkg.from_hstring: Bad string "& hstring severity error; + deallocate (L); + return to_sfixed(result, (hstring'length-1-dot)*4-1, -dot*4); + end if; + end function from_hstring; + +-- synthesis translate_on +-- rtl_synthesis on + function to_StdLogicVector ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_StdLogicVector; + function to_Std_Logic_Vector ( + arg : ufixed) -- fp vector + return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_Std_Logic_Vector; + function to_StdLogicVector ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_StdLogicVector; + function to_Std_Logic_Vector ( + arg : sfixed) -- fp vector + return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_Std_Logic_Vector; + function to_StdULogicVector ( + arg : ufixed) -- fp vector + return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_StdULogicVector; + function to_Std_ULogic_Vector ( + arg : ufixed) -- fp vector + return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_Std_ULogic_Vector; + function to_StdULogicVector ( + arg : sfixed) -- fp vector + return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_StdULogicVector; + function to_Std_ULogic_Vector ( + arg : sfixed) -- fp vector + return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_Std_ULogic_Vector; +end package body fixed_pkg; diff --git a/lib/Standard/ieee_proposed/float_pkg_c.vhd b/lib/Standard/ieee_proposed/float_pkg_c.vhd new file mode 100644 index 0000000..cb2be1b --- /dev/null +++ b/lib/Standard/ieee_proposed/float_pkg_c.vhd @@ -0,0 +1,6133 @@ +------------------------------------------------------------------------------ +-- "float_pkg" package contains functions for floating point math. +-- Please see the documentation for the floating point package. +-- This package should be compiled into "ieee_proposed" and used as follows: +-- use ieee.std_logic_1164.all; +-- use ieee.numeric_std.all; +-- use ieee_proposed.float_pkg.all; +-- Last Modified: $Date: 2006-04-11 08:45:37-04 $ +-- RCS ID: $Id: float_pkg_c.vhd,v 1.5 2006-04-11 08:45:37-04 l435385 Exp $ +-- +-- Created for VHDL-200X par, David Bishop (dbishop@vhdl.org) +------------------------------------------------------------------------------ +library ieee, ieee_proposed; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; +use ieee_proposed.fixed_pkg.all; +-- synthesis translate_off +use std.textio.all; +-- synthesis translate_on + +package float_pkg is + --%%% Uncomment the Generics +-- new work.fixed_generic_pkg +-- generic map ( +-- float_exponent_width => 8; -- float32'high +-- float_fraction_width => 23; -- -float32'low +-- float_round_style => round_nearest; -- round nearest algorithm +-- float_denormalize => true; -- Use IEEE extended floating +-- float_check_error => true; -- Turn on NAN and overflow processing +-- float_guard_bits => 3; -- number of guard bits +-- no_warning => false -- show warnings +-- ); + --%%% REMOVE THE REST OF THIS FILE. + constant float_exponent_width : NATURAL := 8; -- float32'high + constant float_fraction_width : NATURAL := 23; -- -float32'low + constant float_round_style : round_type := round_nearest; -- round nearest algorithm + constant float_denormalize : BOOLEAN := true; -- Use IEEE extended floating + -- point (Denormalized numbers) + constant float_check_error : BOOLEAN := true; -- Turn on NAN and overflow processing + constant float_guard_bits : NATURAL := 3; -- number of guard bits + constant NO_WARNING : BOOLEAN := false; + -- Author David Bishop (dbishop@vhdl.org) + constant CopyRightNotice : STRING := + "Copyright 2005 by IEEE. All rights reserved."; + -- Note that the size of the vector is not defined here, but in + -- the package which calls this one. + type float is array (INTEGER range <>) of STD_LOGIC; -- main type + ----------------------------------------------------------------------------- + -- Use the float type to define your own floating point numbers. + -- There must be a negative index or the packages will error out. + -- Minimum supported is "subtype float7 is float (3 downto -3);" + -- "subtype float16 is float (6 downto -9);" is probably the smallest + -- practical one to use. + ----------------------------------------------------------------------------- + subtype float32 is float (8 downto -23); -- IEEE 754 single precision + ----------------------------------------------------------------------------- + -- IEEE-754 single precision floating point. This is a "float" + -- in C, and a FLOAT in Fortran. The exponent is 8 bits wide, and + -- the fraction is 23 bits wide. This format can hold roughly 7 decimal + -- digits. Infinity is 2**127 = 1.7E38 in this number system. + -- The bit representation is as follows: + -- 1 09876543 21098765432109876543210 + -- 8 76543210 12345678901234567890123 + -- 0 00000000 00000000000000000000000 + -- 8 7 0 -1 -23 + -- +/- exp. fraction + ----------------------------------------------------------------------------- + subtype float64 is float (11 downto -52); -- IEEE 754 double precision + ----------------------------------------------------------------------------- + -- IEEE-754 double precision floating point. This is a "double float" + -- in C, and a FLOAT*8 in Fortran. The exponent is 11 bits wide, and + -- the fraction is 52 bits wide. This format can hold roughly 15 decimal + -- digits. Infinity is 2**2047 in this number system. + -- The bit representation is as follows: + -- 3 21098765432 1098765432109876543210987654321098765432109876543210 + -- 1 09876543210 1234567890123456789012345678901234567890123456789012 + -- S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + -- 11 10 0 -1 -52 + -- +/- exponent fraction + ----------------------------------------------------------------------------- + subtype float128 is float (15 downto -112); -- IEEE 854 & C extended precision + ----------------------------------------------------------------------------- + -- The 128 bit floating point number is "long double" in C (on + -- some systems this is a 70 bit floating point number) and FLOAT*32 + -- in Fortran. The exponent is 15 bits wide and the fraction is 112 + -- bits wide. This number can handel approximately 33 decimal digits. + -- Infinity is 2**32,767 in this number system. + ----------------------------------------------------------------------------- + -- purpose: Checks for a valid floating point number + type valid_fpstate is (nan, -- Signaling NaN (C FP_NAN) + quiet_nan, -- Quiet NaN (C FP_NAN) + neg_inf, -- Negative infinity (C FP_INFINITE) + neg_normal, -- negative normalized nonzero + neg_denormal, -- negative denormalized (FP_SUBNORMAL) + neg_zero, -- -0 (C FP_ZERO) + pos_zero, -- +0 (C FP_ZERO) + pos_denormal, -- Positive denormalized (FP_SUBNORMAL) + pos_normal, -- positive normalized nonzero + pos_inf, -- positive infinity + isx); -- at least one input is unknown + + -- This differed constant will tell you if the package body is synthesizable + -- or implemented as real numbers. + constant fphdlsynth_or_real : BOOLEAN; -- differed constant + -- Returns the class which X falls into + function Class ( + x : float; -- floating point input + check_error : BOOLEAN := float_check_error) -- check for errors + return valid_fpstate; + + -- Arithmetic functions, these operators do not require parameters. + function "abs" (arg : float) return float; + function "-" (arg : float) return float; + -- These allows the base math functions to use the default values + -- of their parameters. Thus they do full IEEE floating point. + function "+" (l, r : float) return float; + function "-" (l, r : float) return float; + function "*" (l, r : float) return float; + function "/" (l, r : float) return float; + function "rem" (l, r : float) return float; + function "mod" (l, r : float) return float; + -- Basic parameter list + -- round_style - Selects the rounding algorithm to use + -- guard - extra bits added to the end if the operation to add precision + -- check_error - When "false" turns off NAN and overflow checks + -- denormalize - When "false" turns off denormal number processing + function add ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function subtract ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function multiply ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function divide ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function remainder ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function modulo ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + -- reciprocal + function reciprocal ( + arg : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function dividebyp2 ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + -- Multiply accumumlate result = l*r + c + function mac ( + l, r, c : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function Is_Negative (arg : float) return BOOLEAN; + + ----------------------------------------------------------------------------- + -- compare functions + -- =, /=, >=, <=, <, >, maximum, minimum + -- These functions are intentionally not implemented in this package, + -- use the "fphdl_pkg" to get this funcitonality. + function eq ( -- equal = + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function ne ( -- not equal /= + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function lt ( -- less than < + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function gt ( -- greater than > + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function le ( -- less than or equal to <= + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + + function ge ( -- greater than or equal to >= + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN; + -- Need to overload the default versions of these + function "=" (l, r : float) return BOOLEAN; + function "/=" (l, r : float) return BOOLEAN; + function ">=" (l, r : float) return BOOLEAN; + function "<=" (l, r : float) return BOOLEAN; + function ">" (l, r : float) return BOOLEAN; + function "<" (l, r : float) return BOOLEAN; + --%%% Uncomment the following (new syntax) +-- function "?=" (l, r : float) return STD_ULOGIC; +-- function "?\=" (l, r : float) return STD_ULOGIC; +-- function "?>" (l, r : float) return STD_ULOGIC; +-- function "?>=" (l, r : float) return STD_ULOGIC; +-- function "?<" (l, r : float) return STD_ULOGIC; +-- function "?<=" (l, r : float) return STD_ULOGIC; + --%%% remove the following (old syntax) + function \?=\ (l, r : float) return STD_ULOGIC; + function \?/=\ (l, r : float) return STD_ULOGIC; + function \?>\ (l, r : float) return STD_ULOGIC; + function \?>=\ (l, r : float) return STD_ULOGIC; + function \?<\ (l, r : float) return STD_ULOGIC; + function \?<=\ (l, r : float) return STD_ULOGIC; + function std_match (l, r : float) return BOOLEAN; + function find_lsb (arg : float; y : STD_ULOGIC) return INTEGER; + function find_msb (arg : float; y : STD_ULOGIC) return INTEGER; + function maximum (l, r : float) return float; + function minimum (l, r : float) return float; + -- conversion functions + -- Converts one floating point number into another. + function resize ( + arg : float; -- Floating point input + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function resize ( + arg : float; -- Floating point input + size_res : float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function to_float32 ( + arg : float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function to_float64 ( + arg : float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + function to_float128 ( + arg : float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + -- Converts an fp into an SLV (needed for synthesis) + function to_slv (arg : float) return STD_LOGIC_VECTOR; +-- alias to_StdLogicVector is to_slv [float return STD_LOGIC_VECTOR]; +-- alias to_Std_Logic_Vector is to_slv [float return STD_LOGIC_VECTOR]; + + -- Converts an fp into an SULV + function to_sulv (arg : float) return STD_ULOGIC_VECTOR; +-- alias to_StdULogicVector is to_sulv [float return STD_ULOGIC_VECTOR]; +-- alias to_Std_ULogic_Vector is to_sulv [float return STD_ULOGIC_VECTOR]; + + -- std_logic_vector to float + function to_float ( + arg : STD_LOGIC_VECTOR; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction + return float; + + -- std_ulogic_vector to float + function to_float ( + arg : STD_ULOGIC_VECTOR; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction + return float; + + -- Integer to float + function to_float ( + arg : INTEGER; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return float; + + -- real to float + function to_float ( + arg : REAL; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + -- unsigned to float + function to_float ( + arg : UNSIGNED; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return float; + + -- signed to float + function to_float ( + arg : SIGNED; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return float; + + -- unsigned fixed point to float + function to_float ( + arg : ufixed; -- unsigned fixed point input + constant exponent_width : NATURAL := float_exponent_width; -- width of exponent + constant fraction_width : NATURAL := float_fraction_width; -- width of fraction + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- use ieee extentions + return float; + + -- signed fixed point to float + function to_float ( + arg : sfixed; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- rounding option + return float; + + -- size_res functions + -- Integer to float + function to_float ( + arg : INTEGER; + size_res : float; + constant round_style : round_type := float_round_style) -- rounding option + return float; + + -- real to float + function to_float ( + arg : REAL; + size_res : float; + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + -- unsigned to float + function to_float ( + arg : UNSIGNED; + size_res : float; + constant round_style : round_type := float_round_style) -- rounding option + return float; + + -- signed to float + function to_float ( + arg : SIGNED; + size_res : float; + constant round_style : round_type := float_round_style) -- rounding option + return float; + + -- slv to float + function to_float ( + arg : STD_LOGIC_VECTOR; + size_res : float) + return float; + + -- sulv to float + function to_float ( + arg : STD_ULOGIC_VECTOR; + size_res : float) + return float; + + -- unsigned fixed point to float + function to_float ( + arg : ufixed; -- unsigned fixed point input + size_res : float; + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- use ieee extentions + return float; + + -- signed fixed point to float + function to_float ( + arg : sfixed; + size_res : float; + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- rounding option + return float; + + -- float to unsigned + function to_unsigned ( + arg : float; -- floating point input + constant size : NATURAL; -- length of output + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return UNSIGNED; + + -- float to signed + function to_signed ( + arg : float; -- floating point input + constant size : NATURAL; -- length of output + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return SIGNED; + + -- purpose: Converts a float to unsigned fixed point + function to_ufixed ( + arg : float; -- fp input + constant left_index : INTEGER; -- integer part + constant right_index : INTEGER; -- fraction part + constant round_style : BOOLEAN := fixed_round_style; -- rounding + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return ufixed; + + -- float to signed fixed point + function to_sfixed ( + arg : float; -- fp input + constant left_index : INTEGER; -- integer part + constant right_index : INTEGER; -- fraction part + constant round_style : BOOLEAN := fixed_round_style; -- rounding + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return sfixed; + + -- size_res versions + -- float to unsigned + function to_unsigned ( + arg : float; -- floating point input + size_res : UNSIGNED; + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return UNSIGNED; + + -- float to signed + function to_signed ( + arg : float; -- floating point input + size_res : SIGNED; + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return SIGNED; + + -- purpose: Converts a float to unsigned fixed point + function to_ufixed ( + arg : float; -- fp input + size_res : ufixed; + constant round_style : BOOLEAN := fixed_round_style; -- rounding + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return ufixed; + + -- float to signed fixed point + function to_sfixed ( + arg : float; -- fp input + size_res : sfixed; + constant round_style : BOOLEAN := fixed_round_style; -- rounding + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return sfixed; + + -- float to real + function to_real ( + arg : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return REAL; + + -- float to integer + function to_integer ( + arg : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return INTEGER; + + -- Maps metalogical values + function to_01 ( + arg : float; -- floating point input + XMAP : STD_LOGIC := '0') + return float; + + function Is_X (arg : float) return BOOLEAN; + function to_X01 (arg : float) return float; + function to_X01Z (arg : float) return float; + function to_UX01 (arg : float) return float; + + -- These two procedures were copied out of the body because they proved + -- very useful for vendor specific algorithm development + -- Break_number converts a floating point number into it's parts + -- Exponend is biased by -1 + procedure break_number ( + arg : in float; + denormalize : in BOOLEAN := float_denormalize; + check_error : in BOOLEAN := float_check_error; + fract : out UNSIGNED; + expon : out SIGNED; -- NOTE: Add 1 to get the real exponent! + sign : out STD_ULOGIC); + + procedure break_number ( + arg : in float; + denormalize : in BOOLEAN := float_denormalize; + check_error : in BOOLEAN := float_check_error; + fract : out ufixed; -- a number between 1.0 and 2.0 + expon : out SIGNED; -- NOTE: Add 1 to get the real exponent! + sign : out STD_ULOGIC); + + -- Normalize takes a fraction and and exponent and converts them into + -- a floating point number. Does the shifting and the rounding. + -- Exponend is assumed to be biased by -1 + function normalize ( + fract : UNSIGNED; -- fraction, unnormalized + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent + constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return float; + + -- Exponend is assumed to be biased by -1 + function normalize ( + fract : ufixed; -- unsigned fixed point + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent + constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return float; + + function normalize ( + fract : UNSIGNED; -- unsigned + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + size_res : float; -- used for sizing only + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return float; + + -- Exponend is assumed to be biased by -1 + function normalize ( + fract : ufixed; -- unsigned fixed point + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + size_res : float; -- used for sizing only + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return float; + + -- overloaded versions + function "+" (l : float; r : REAL) return float; + function "+" (l : REAL; r : float) return float; + function "+" (l : float; r : INTEGER) return float; + function "+" (l : INTEGER; r : float) return float; + function "-" (l : float; r : REAL) return float; + function "-" (l : REAL; r : float) return float; + function "-" (l : float; r : INTEGER) return float; + function "-" (l : INTEGER; r : float) return float; + function "*" (l : float; r : REAL) return float; + function "*" (l : REAL; r : float) return float; + function "*" (l : float; r : INTEGER) return float; + function "*" (l : INTEGER; r : float) return float; + function "/" (l : float; r : REAL) return float; + function "/" (l : REAL; r : float) return float; + function "/" (l : float; r : INTEGER) return float; + function "/" (l : INTEGER; r : float) return float; + function "rem" (l : float; r : REAL) return float; + function "rem" (l : REAL; r : float) return float; + function "rem" (l : float; r : INTEGER) return float; + function "rem" (l : INTEGER; r : float) return float; + function "mod" (l : float; r : REAL) return float; + function "mod" (l : REAL; r : float) return float; + function "mod" (l : float; r : INTEGER) return float; + function "mod" (l : INTEGER; r : float) return float; + function "=" (l : float; r : REAL) return BOOLEAN; + function "/=" (l : float; r : REAL) return BOOLEAN; + function ">=" (l : float; r : REAL) return BOOLEAN; + function "<=" (l : float; r : REAL) return BOOLEAN; + function ">" (l : float; r : REAL) return BOOLEAN; + function "<" (l : float; r : REAL) return BOOLEAN; + function "=" (l : REAL; r : float) return BOOLEAN; + function "/=" (l : REAL; r : float) return BOOLEAN; + function ">=" (l : REAL; r : float) return BOOLEAN; + function "<=" (l : REAL; r : float) return BOOLEAN; + function ">" (l : REAL; r : float) return BOOLEAN; + function "<" (l : REAL; r : float) return BOOLEAN; + function "=" (l : float; r : INTEGER) return BOOLEAN; + function "/=" (l : float; r : INTEGER) return BOOLEAN; + function ">=" (l : float; r : INTEGER) return BOOLEAN; + function "<=" (l : float; r : INTEGER) return BOOLEAN; + function ">" (l : float; r : INTEGER) return BOOLEAN; + function "<" (l : float; r : INTEGER) return BOOLEAN; + function "=" (l : INTEGER; r : float) return BOOLEAN; + function "/=" (l : INTEGER; r : float) return BOOLEAN; + function ">=" (l : INTEGER; r : float) return BOOLEAN; + function "<=" (l : INTEGER; r : float) return BOOLEAN; + function ">" (l : INTEGER; r : float) return BOOLEAN; + function "<" (l : INTEGER; r : float) return BOOLEAN; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : float) return float; + function "and" (L, R : float) return float; + function "or" (L, R : float) return float; + function "nand" (L, R : float) return float; + function "nor" (L, R : float) return float; + function "xor" (L, R : float) return float; + function "xnor" (L, R : float) return float; + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (L : STD_ULOGIC; R : float) return float; + function "and" (L : float; R : STD_ULOGIC) return float; + function "or" (L : STD_ULOGIC; R : float) return float; + function "or" (L : float; R : STD_ULOGIC) return float; + function "nand" (L : STD_ULOGIC; R : float) return float; + function "nand" (L : float; R : STD_ULOGIC) return float; + function "nor" (L : STD_ULOGIC; R : float) return float; + function "nor" (L : float; R : STD_ULOGIC) return float; + function "xor" (L : STD_ULOGIC; R : float) return float; + function "xor" (L : float; R : STD_ULOGIC) return float; + function "xnor" (L : STD_ULOGIC; R : float) return float; + function "xnor" (L : float; R : STD_ULOGIC) return float; + -- Reduction operators, same as numeric_std functions + -- %%% remove 6 functions (old syntax) + function and_reduce (arg : float) return STD_ULOGIC; + function nand_reduce (arg : float) return STD_ULOGIC; + function or_reduce (arg : float) return STD_ULOGIC; + function nor_reduce (arg : float) return STD_ULOGIC; + function xor_reduce (arg : float) return STD_ULOGIC; + function xnor_reduce (arg : float) return STD_ULOGIC; + -- %%% Uncomment the following 6 functions (new syntax) + -- function "and" (arg : float) RETURN std_ulogic; + -- function "nand" (arg : float) RETURN std_ulogic; + -- function "or" (arg : float) RETURN std_ulogic; + -- function "nor" (arg : float) RETURN std_ulogic; + -- function "xor" (arg : float) RETURN std_ulogic; + -- function "xnor" (arg : float) RETURN std_ulogic; + + -- Note: "sla", "sra", "sll", "slr", "rol" and "ror" not implemented. + -- Note: "find_msb" and "find_lsb" not implemented, use "logb". + ----------------------------------------------------------------------------- + -- Recommended Functions from the IEEE 754 Appendix + ----------------------------------------------------------------------------- + -- returns x with the sign of y. + function Copysign (x, y : float) return float; + + -- Returns y * 2**n for intergral values of N without computing 2**n + function Scalb ( + y : float; -- floating point input + N : INTEGER; -- exponent to add + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + -- Returns y * 2**n for intergral values of N without computing 2**n + function Scalb ( + y : float; -- floating point input + N : SIGNED; -- exponent to add + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float; + + -- returns the unbiased exponent of x + function Logb (x : float) return INTEGER; + function Logb (x : float) return SIGNED; + + -- returns the next represtable neighbor of x in the direction toward y + function Nextafter ( + x, y : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return float; + + -- Returns TRUE if X is unordered with Y. + function Unordered (x, y : float) return BOOLEAN; + function Finite (x : float) return BOOLEAN; + function Isnan (x : float) return BOOLEAN; + + -- Function to return constants. + function zerofp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float; + function nanfp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float; + function qnanfp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float; + function pos_inffp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float; + function neg_inffp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float; + function neg_zerofp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float; + -- size_res versions + function zerofp ( + size_res : float) -- variable is only use for sizing + return float; + function nanfp ( + size_res : float) -- variable is only use for sizing + return float; + function qnanfp ( + size_res : float) -- variable is only use for sizing + return float; + function pos_inffp ( + size_res : float) -- variable is only use for sizing + return float; + function neg_inffp ( + size_res : float) -- variable is only use for sizing + return float; + function neg_zerofp ( + size_res : float) -- variable is only use for sizing + return float; + +-- synthesis translate_off +-- rtl_synthesis off + -- impure functions + -- writes S:EEEE:FFFFFFFF + procedure write ( + L : inout LINE; -- access type (pointer) + VALUE : in float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0); -- width of field + + -- Reads SEEEEFFFFFFFF, "." and ":" are ignored + procedure READ(L : inout LINE; VALUE : out float); + procedure READ(L : inout LINE; VALUE : out float; GOOD : out BOOLEAN); + + alias bread is READ [LINE, float, BOOLEAN]; + alias bread is READ [LINE, float]; + alias bwrite is WRITE [LINE, float, SIDE, WIDTH]; + + procedure owrite ( + L : inout LINE; -- access type (pointer) + VALUE : in float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0); -- width of field + + -- Octal read with padding, no seperaters used + procedure OREAD(L : inout LINE; VALUE : out float); + procedure OREAD(L : inout LINE; VALUE : out float; GOOD : out BOOLEAN); + + -- Hex write with padding, no seperators + procedure hwrite ( + L : inout LINE; -- access type (pointer) + VALUE : in float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0); -- width of field + + -- Hex read with padding, no seperaters used + procedure HREAD(L : inout LINE; VALUE : out float); + procedure HREAD(L : inout LINE; VALUE : out float; GOOD : out BOOLEAN); + + -- returns "S:EEEE:FFFFFFFF" + function to_string ( + value : float; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + -- Returns a HEX string, with padding + function to_hstring ( + value : float; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + -- Returns and octal string, with padding + function to_ostring ( + value : float; + justified : SIDE := right; + field : WIDTH := 0 + ) return STRING; + + function from_string ( + bstring : STRING; -- binary string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return float; + alias from_bstring is from_string [STRING, NATURAL, NATURAL return float]; + + function from_ostring ( + ostring : STRING; -- Octal string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return float; + + function from_hstring ( + hstring : STRING; -- hex string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return float; + + function from_string ( + bstring : STRING; -- binary string + size_res : float) -- used for sizing only + return float; + alias from_bstring is from_string [STRING, float return float]; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : float) -- used for sizing only + return float; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : float) -- used for sizing only + return float; + +-- synthesis translate_on +-- rtl_synthesis on + + function to_StdLogicVector (arg : float) return std_logic_vector ; + function to_Std_Logic_Vector (arg : float) return std_logic_vector; + function to_StdULogicVector (arg : float) return std_ulogic_vector ; + function to_Std_ULogic_Vector (arg : float) return std_ulogic_vector; + +end package float_pkg; +library ieee; +use ieee.math_real.all; +use ieee.std_logic_textio.all; -- %%% for testing only +package body float_pkg is + -- Author David Bishop (dbishop@vhdl.org) + ----------------------------------------------------------------------------- + -- type declarations + ----------------------------------------------------------------------------- + -- This differed constant will tell you if the package body is synthesizable + -- or implemented as real numbers, set to "true" if synthesizable. + constant fphdlsynth_or_real : BOOLEAN := true; -- differed constant + -- types of boundary conditions + type boundary_type is (normal, infinity, zero, denormal); + -- null range array constant + constant NAFP : float (0 downto 1) := (others => '0'); + constant NSLV : STD_LOGIC_VECTOR (0 downto 1) := (others => '0'); + + -- %%% These functions can be removed in the final release. + -- %%% Replace and_reducex with "and" (and all similar _reducex functions) + -- purpose: AND all of the bits in a vector together + -- This is a copy of the proposed "and_reduce" from 1076.3 + function and_reducex (arg : STD_LOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_LOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_LOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '1'; -- Change for version 1.3 + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) and BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := and_reducex (BUS_int (BUS_int'left downto Half)); + Lower := and_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper and Lower; + end if; + end if; + return Result; + end function and_reducex; + + function and_reducex (arg : UNSIGNED) + return STD_LOGIC is + begin + return and_reducex (STD_LOGIC_VECTOR (arg)); + end function and_reducex; + + -- purpose: OR all of the bits in a vector together + -- This is a copy of the proposed "and_reduce" from 1076.3 + function or_reducex (arg : STD_LOGIC_VECTOR) + return STD_LOGIC is + variable Upper, Lower : STD_LOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_LOGIC; + begin + if (arg'length < 1) then -- In the case of a NULL range + Result := '0'; + else + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int (BUS_int'right) or BUS_int (BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := or_reducex (BUS_int (BUS_int'left downto Half)); + Lower := or_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper or Lower; + end if; + end if; + return Result; + end function or_reducex; + + function or_reducex (arg : UNSIGNED) + return STD_LOGIC is + begin + return or_reducex (STD_LOGIC_VECTOR (arg)); + end function or_reducex; + + function xor_reducex (arg : STD_LOGIC_VECTOR) return STD_ULOGIC is + variable Upper, Lower : STD_ULOGIC; + variable Half : INTEGER; + variable BUS_int : STD_LOGIC_VECTOR (arg'length - 1 downto 0); + variable Result : STD_ULOGIC := '0'; -- In the case of a NULL range + begin + if (arg'length >= 1) then + BUS_int := to_ux01 (arg); + if (BUS_int'length = 1) then + Result := BUS_int (BUS_int'left); + elsif (BUS_int'length = 2) then + Result := BUS_int(BUS_int'right) xor BUS_int(BUS_int'left); + else + Half := (BUS_int'length + 1) / 2 + BUS_int'right; + Upper := xor_reducex (BUS_int (BUS_int'left downto Half)); + Lower := xor_reducex (BUS_int (Half - 1 downto BUS_int'right)); + Result := Upper xor Lower; + end if; + end if; + return Result; + end function xor_reducex; + + -- purpose: To find the largest of 2 numbers + -- %%% Will be implicit in VHDL-200X + function maximum ( + l, r : INTEGER) -- inputs + return INTEGER is + begin -- function max + if l > r then return l; + else return r; + end if; + end function maximum; + + -- purpose: Find the first "1" is a vector, starting from the MSB + -- %%% This is a copy of the proposed "find_msb" from 1076.3 + function find_msb ( + arg : UNSIGNED; -- vector argument + y : STD_ULOGIC) -- look for this bit + return INTEGER is + alias xarg : UNSIGNED(arg'length-1 downto 0) is arg; + begin + for_loop : for i in xarg'range loop + if xarg(i) = y then + return i; + end if; + end loop; + return -1; + end function find_msb; + -- %%% End remove + + -- Special version of "minimum" to do some boundary checking + function minx (l, r : INTEGER) + return INTEGER is + begin -- function minimum + if (L = INTEGER'low or R = INTEGER'low) then + report "FLOAT_GENERIC_PKG: Unbounded number passed, was a literal used?" + severity error; + return 0; + end if; + if L > R then return R; + else return L; + end if; + end function minx; + + -- Generates the base number for the exponent normalization offset. + function gen_expon_base ( + constant exponent_width : NATURAL) + return SIGNED is + variable result : SIGNED (exponent_width-1 downto 0); + begin + result := (others => '1'); + result (exponent_width-1) := '0'; + return result; + end function gen_expon_base; + + -- purpose: Test the boundary conditions of a Real number +-- function test_boundary ( +-- arg : REAL; -- Input, converted to real +-- constant fraction_width : NATURAL; -- length of FP output fraction +-- constant exponent_width : NATURAL; -- length of FP exponent +-- constant denormalize : BOOLEAN := true) -- Use IEEE extended FP +-- return boundary_type is +-- constant expon_base : SIGNED (exponent_width-1 downto 0) := +-- gen_expon_base(exponent_width); -- exponent offset +-- constant exp_min : SIGNED (12 downto 0) := +-- -(resize(expon_base, 13)) +1; -- Minimum normal exponent +-- constant exp_ext_min : SIGNED (12 downto 0) := +-- exp_min - fraction_width; -- Minimum for denormal exponent +-- begin -- function test_boundary +-- -- Check to see if the exponent is big enough +-- -- Note that the argument is always an absolute value at this point. +-- if arg = 0.0 then +-- return zero; +-- elsif exponent_width > 11 then -- Exponent for Real is 11 (64 bit) +-- return normal; +-- else +-- if arg < 2.0 ** to_integer(exp_min) then +-- if denormalize then +-- if arg < 2.0 ** to_integer(exp_ext_min) then +-- return zero; +-- else +-- return denormal; +-- end if; +-- else +-- if arg < 2.0 ** to_integer(exp_min-1) then +-- return zero; +-- else +-- return normal; -- Can still represent this number +-- end if; +-- end if; +-- elsif exponent_width < 11 then +-- if arg >= 2.0 ** (to_integer(expon_base)+1) then +-- return infinity; +-- else +-- return normal; +-- end if; +-- else +-- return normal; +-- end if; +-- end if; +-- end function test_boundary; + + -- Some synthesis tools don't like this function, so do it this way + -- (ignoring denormal and infinite numbers) + function test_boundary ( + arg : REAL; -- Input, converted to real + constant fraction_width : NATURAL; -- length of FP output fraction + constant exponent_width : NATURAL; -- length of FP exponent + constant denormalize : BOOLEAN := true) -- Use IEEE extended FP + return boundary_type is + begin -- function test_boundary + if arg = 0.0 then + return zero; + else + return normal; + end if; + end function test_boundary; + + -- purpose: Rounds depending on the state of the "round_style" + -- unsigned version + function check_round ( + fract_in : STD_ULOGIC; -- input fraction + sign : STD_ULOGIC; -- sign bit + remainder : UNSIGNED; -- remainder to round from + sticky : STD_ULOGIC := '0'; -- Sticky bit + constant round_style : round_type) -- rounding type + return BOOLEAN is + variable result : BOOLEAN; + variable or_reduced : STD_ULOGIC; + begin -- function check_round + result := false; + if (remainder'length > 0) then -- if remainder in a null array + or_reduced := or_reducex (remainder & sticky); + rounding_case : case round_style is + when round_nearest => -- Round Nearest, default mode + if remainder(remainder'high) = '1' then -- round + if (remainder'length > 1) then + if ((or_reducex (remainder(remainder'high-1 + downto remainder'low)) = '1' + or sticky = '1') + or fract_in = '1') then + -- Make the bottom bit zero if possible if we are at 1/2 + result := true; + end if; + else + result := (fract_in = '1' or sticky = '1'); + end if; + end if; + when round_inf => -- round up if positive, else truncate. + if or_reduced = '1' and sign = '0' then + result := true; + end if; + when round_neginf => -- round down if negative, else truncate. + if or_reduced = '1' and sign = '1' then + result := true; + end if; + when round_zero => -- round toward 0 Truncate + null; + end case rounding_case; + end if; + return result; + end function check_round; + + -- purpose: Rounds depending on the state of the "round_style" + -- unsigned version + procedure fp_round ( + fract_in : in UNSIGNED; -- input fraction + expon_in : in SIGNED; -- input exponent + fract_out : out UNSIGNED; -- output fraction + expon_out : out SIGNED) is -- output exponent + begin -- procedure fp_round + if and_reducex(fract_in) = '1' then -- Fraction is all "1" + expon_out := expon_in + 1; + fract_out := to_unsigned(0, fract_out'high+1); + else + expon_out := expon_in; + fract_out := fract_in + 1; + end if; + end procedure fp_round; + + -- Integer version of the "log2" command + -- Synthisable, used by to_float(integer) function + function log2(A : NATURAL) return NATURAL is + begin + for I in 1 to 30 loop -- Works for up to 32 bit integers + if (2**I > A) then return(I-1); + end if; + end loop; + return(30); + end function log2; + + -- purpose: Look for the boundaries of the integer input + -- Synthisable + function fp_input_type ( + arg : INTEGER; -- integer input + constant fraction_width : NATURAL; -- length of FP output fraction + constant exponent_width : NATURAL) -- length of FP output exponent + return boundary_type is + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable maxint : INTEGER; + begin -- function fp_input_type + if arg = 0 then + return zero; + elsif exponent_width > 5 then -- largest possible integer = 2**31 + return normal; + else + maxint := 2 ** (to_integer(expon_base)+1); + -- worry about infinity + if arg >= maxint then + return infinity; + else + return normal; + end if; + end if; + end function fp_input_type; + + procedure break_number ( -- internal version + arg : in float; + fptyp : in valid_fpstate; + denormalize : in BOOLEAN := true; + fract : out UNSIGNED; + expon : out SIGNED) is + constant fraction_width : NATURAL := -arg'low; -- length of FP output fraction + constant exponent_width : NATURAL := arg'high; -- length of FP output exponent + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable exp : SIGNED (expon'range); + begin + fract (fraction_width-1 downto 0) := + UNSIGNED (to_slv(arg(-1 downto -fraction_width))); + breakcase : case fptyp is + when pos_zero | neg_zero => + fract (fraction_width) := '0'; + exp := -expon_base; + when pos_denormal | neg_denormal => + if denormalize then + exp := -expon_base; + fract (fraction_width) := '0'; + else + exp := -expon_base - 1; + fract (fraction_width) := '1'; + end if; + when pos_normal | neg_normal => + fract (fraction_width) := '1'; + exp := SIGNED(arg(exponent_width-1 downto 0)); + exp (exponent_width-1) := not exp(exponent_width-1); + when others => + assert NO_WARNING + report "FLOAT_GENERIC_PKG.BREAK_NUMBER: " & + "Meta state detected in fp_break_number process" + severity warning; + -- complete the case, if a NAN goes in, a NAN comes out. + exp := (others => '1'); + fract (fraction_width) := '1'; + end case breakcase; + expon := exp; + end procedure break_number; + + -- purpose: floating point to UNSIGNED + -- Used by to_integer, to_unsigned, and to_signed functions + procedure float_to_unsigned ( + arg : in float; -- floating point input + variable sign : out STD_ULOGIC; -- sign of output + variable frac : out UNSIGNED; -- unsigned biased output + constant denormalize : in BOOLEAN; -- turn on denormalization + constant bias : in NATURAL; -- bias for fixed point + constant round_style : in round_type) is -- rounding method + constant fraction_width : INTEGER := -minx(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : INTEGER := arg'high; -- length of FP output exponent + variable fract : UNSIGNED (frac'range); -- internal version of frac + variable isign : STD_ULOGIC; -- internal version of sign + variable exp : INTEGER; -- Exponent + variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp + -- Base to divide fraction by + variable frac_shift : UNSIGNED (frac'high+3 downto 0); -- Fraction shifted + variable shift : INTEGER; + variable remainder : UNSIGNED (2 downto 0); + variable round : STD_ULOGIC; -- round BIT + begin + isign := to_x01(arg(arg'high)); + -- exponent /= '0', normal floating point + expon := to_01(SIGNED(arg (exponent_width-1 downto 0)), 'X'); + expon(exponent_width-1) := not expon(exponent_width-1); + exp := to_integer (expon); + -- Figure out the fraction + fract := (others => '0'); -- fill with zero + fract (fract'high) := '1'; -- Add the "1.0". + shift := (fract'high-1) - exp; + if fraction_width > fract'high then -- Can only use size-2 bits + fract (fract'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto + -fract'high))); + else -- can use all bits + fract (fract'high-1 downto fract'high-fraction_width) := + UNSIGNED (to_slv (arg(-1 downto -fraction_width))); + end if; + frac_shift := fract & "000"; + if shift < 0 then -- Overflow + fract := (others => '1'); + else + frac_shift := shift_right (frac_shift, shift); + fract := frac_shift (frac_shift'high downto 3); + remainder := frac_shift (2 downto 0); + -- round (round_zero will bypass this and truncate) + case round_style is + when round_nearest => + round := remainder(2) and + (fract (0) or or_reducex (remainder (1 downto 0))); + when round_inf => + round := remainder(2) and not isign; + when round_neginf => + round := remainder(2) and isign; + when others => + round := '0'; + end case; + if round = '1' then + fract := fract + 1; + end if; + end if; + frac := fract; + sign := isign; + end procedure float_to_unsigned; + + -- purpose: returns a part of a string, this funciton is here because + -- or_reducex (fractr (to_integer(shiftx) downto 0)); + -- can't be synthesized in some synthesis tools. + function smallfract ( + arg : UNSIGNED; + shift : natural) + return std_ulogic is + variable orx : STD_ULOGIC; + begin + orx := arg(shift); + for i in arg'range loop + if i < shift then + orx := arg(i) or orx; + end if; + end loop; + return orx; + end function smallfract; + --------------------------------------------------------------------------- + -- Visible functions + --------------------------------------------------------------------------- + + -- purpose: converts the negative index to a positive one + -- negative indices are illegal in 1164 and 1076.3 + function to_slv ( + arg : float) -- fp vector + return STD_LOGIC_VECTOR is + subtype t is STD_LOGIC_VECTOR(arg'length - 1 downto 0); + variable slv : t; + begin -- function to_std_logic_vector + if arg'length < 1 then + return NSLV; + end if; + slv := t(arg); +-- floop : for i in slv'range loop +-- slv(i) := arg(i + arg'low); -- slv(31) := arg (31-23) +-- end loop floop; + return slv; + end function to_slv; + + -- Converts an fp into an SULV + function to_sulv (arg : float) return STD_ULOGIC_VECTOR is + begin + return to_stdulogicvector (to_slv(arg)); + end function to_sulv; + + -- purpose: normalizes a floating point number + -- This version assumes an "unsigned" input with + function normalize ( + fract : UNSIGNED; -- fraction, unnormalized + expon : SIGNED; -- exponent, normalized by -1 + sign : STD_ULOGIC; -- sign BIT + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent + constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return float is + variable sfract : UNSIGNED (fract'high downto 0); -- shifted fraction + variable rfract : UNSIGNED (fraction_width-1 downto 0); -- fraction + variable exp : SIGNED (exponent_width+1 downto 0); -- exponent + variable rexp : SIGNED (exponent_width+1 downto 0); -- result exponent + variable rexpon : UNSIGNED (exponent_width-1 downto 0); -- exponent + variable result : float (exponent_width downto -fraction_width); -- result + variable shiftr : INTEGER; -- shift amount + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable round : BOOLEAN; + begin -- function normalize + result (exponent_width) := sign; -- sign bit + round := false; + shiftr := find_msb (to_01(fract), '1') -- Find the first "1" + - fraction_width - nguard; -- subtract the length we want + exp := resize (expon, exp'length) + shiftr; + if (or_reducex(fract) = '0') then -- Zero + result := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif ((exp <= -resize(expon_base, exp'length)-1) and denormalize) + or ((exp < -resize(expon_base, exp'length)-1) and not denormalize) then + if (exp >= -resize(expon_base, exp'length)-fraction_width-1) + and denormalize then + exp := -resize(expon_base, exp'length); + shiftr := to_integer (expon + expon_base); -- new shift + sfract := fract sll shiftr; -- shift + if nguard > 0 then + round := check_round ( + fract_in => sfract (nguard), + sign => sign, + remainder => sfract(nguard-1 downto 0), + round_style => round_style); + end if; + if round then + fp_round(fract_in => sfract (fraction_width-1+nguard downto nguard), + expon_in => exp, + fract_out => rfract, + expon_out => rexp); + else + rfract := sfract (fraction_width-1+nguard downto nguard); + rexp := exp; + end if; + rexpon := UNSIGNED ((rexp(exponent_width-1 downto 0))-1); + rexpon(exponent_width-1) := not rexpon(exponent_width-1); + result (rexpon'range) := float(rexpon); + result (-1 downto -fraction_width) := float(rfract); + else -- return zero + result := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + end if; + elsif (exp > expon_base-1) then -- infinity + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + result (exponent_width) := sign; -- redo sign bit for neg inf. + else -- normal number + sfract := fract srl shiftr; -- shift + if nguard > 0 then + round := check_round ( + fract_in => sfract (nguard), + sign => sign, + remainder => sfract(nguard-1 downto 0), + sticky => sticky, + round_style => round_style); + end if; + if round then + fp_round(fract_in => sfract (fraction_width-1+nguard downto nguard), + expon_in => exp(rexp'range), + fract_out => rfract, + expon_out => rexp); + else + rfract := sfract (fraction_width-1+nguard downto nguard); + rexp := exp(rexp'range); + end if; + -- result + rexpon := UNSIGNED (rexp(exponent_width-1 downto 0)); + rexpon(exponent_width-1) := not rexpon(exponent_width-1); + result (rexpon'range) := float(rexpon); + result (-1 downto -fraction_width) := float(rfract); + end if; + return result; + end function normalize; + + -- purpose: normalizes a floating point number + -- This version assumes a "ufixed" input with + function normalize ( + fract : ufixed; -- unsigned fixed point + expon : SIGNED; -- exponent, normalized by -1 + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + constant exponent_width : NATURAL := float_exponent_width; -- size of output exponent + constant fraction_width : NATURAL := float_fraction_width; -- size of output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return float is + variable result : float (exponent_width downto -fraction_width); + variable arguns : UNSIGNED (fract'high + fraction_width + nguard + downto 0) := (others => '0'); + begin -- function normalize + for i in arguns'high downto maximum (arguns'high-fract'length+1, 0) loop + arguns (i) := fract (fract'high + (i-arguns'high)); + end loop; + result := normalize (fract => arguns, + expon => expon, + sign => sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => nguard); + return result; + end function normalize; + + -- purpose: normalizes a floating point number + -- This version assumes a "ufixed" input with + function normalize ( + fract : ufixed; -- unsigned fixed point + expon : SIGNED; -- exponent, normalized by -1 + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + size_res : float; -- used for sizing only + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return float is + constant fraction_width : NATURAL := -size_res'low; + constant exponent_width : NATURAL := size_res'high; + variable result : float (exponent_width downto -fraction_width); + variable arguns : UNSIGNED (fract'high + fraction_width + nguard + downto 0) := (others => '0'); + begin -- function normalize + for i in arguns'high downto maximum (arguns'high-fract'length+1, 0) loop + arguns (i) := fract (fract'high + (i-arguns'high)); + end loop; + result := normalize (fract => arguns, + expon => expon, + sign => sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => nguard); + return result; + end function normalize; + + function normalize ( + fract : UNSIGNED; -- unsigned + expon : SIGNED; -- exponent - 1, normalized + sign : STD_ULOGIC; -- sign bit + sticky : STD_ULOGIC := '0'; -- Sticky bit (rounding) + size_res : float; -- used for sizing only + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant nguard : NATURAL := float_guard_bits) -- guard bits + return float is + begin + return normalize (fract => fract, + expon => expon, + sign => sign, + sticky => sticky, + fraction_width => -size_res'low, + exponent_width => size_res'high, + round_style => round_style, + denormalize => denormalize, + nguard => nguard); + end function normalize; + -- Returns the class which X falls into + -- Synthisable + function Class ( + x : float; -- floating point input + check_error : BOOLEAN := float_check_error) -- check for errors + return valid_fpstate is + constant fraction_width : INTEGER := -minx(x'low, x'low); -- length of FP output fraction + constant exponent_width : INTEGER := x'high; -- length of FP output exponent + variable arg : float (exponent_width downto -fraction_width); + begin -- class + if (arg'length < 1 or fraction_width < 3 or exponent_width < 3 + or x'left < x'right) then + report "FLOAT_GENERIC_PKG.CLASS: " & + "Floating point number detected with a bad range" + severity error; + return isx; + end if; + -- Check for "X". + arg := to_01 (x, 'X'); + if (arg(0) = 'X') then + return isx; -- If there is an X in the number + -- Special cases, check for illegal number + elsif check_error and + and_reducex (STD_LOGIC_VECTOR (arg (exponent_width-1 downto 0))) + = '1' then -- Exponent is all "1". + if or_reducex (to_slv (arg (-1 downto -fraction_width))) + /= '0' then -- Fraction must be all "0" or this is not a number. + if (arg(-1) = '1') then -- From "W. Khan - IEEE standard + return nan; -- 754 binary FP Signaling nan (Not a number) + else + return quiet_nan; + end if; + -- Check for infinity + elsif arg(exponent_width) = '0' then + return pos_inf; -- Positive infinity + else + return neg_inf; -- Negative infinity + end if; + -- check for "0" + elsif or_reducex (STD_LOGIC_VECTOR (arg (exponent_width-1 downto 0))) + = '0' then -- Exponent is all "0" + if or_reducex (to_slv (arg(-1 downto -fraction_width))) + = '0' then -- Fraction is all "0" + if arg(exponent_width) = '0' then + return pos_zero; -- Zero + else + return neg_zero; + end if; + else + if arg(exponent_width) = '0' then + return pos_denormal; -- Denormal number (ieee extended fp) + else + return neg_denormal; + end if; + end if; + else + if arg(exponent_width) = '0' then + return pos_normal; -- Normal FP number + else + return neg_normal; + end if; + end if; + end function Class; + + procedure break_number ( + arg : in float; + denormalize : in BOOLEAN := float_denormalize; + check_error : in BOOLEAN := float_check_error; + fract : out UNSIGNED; + expon : out SIGNED; + sign : out STD_ULOGIC) is + constant fraction_width : NATURAL := -minx(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : NATURAL := arg'high; -- length of FP output exponent + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable fptyp : valid_fpstate; + variable exp : SIGNED (expon'range); + begin + fptyp := Class (arg, check_error); + fract (fraction_width-1 downto 0) := + UNSIGNED (to_slv(arg(-1 downto -fraction_width))); + sign := to_x01(arg(arg'high)); + breakcase : case fptyp is + when pos_zero | neg_zero => + fract (fraction_width) := '0'; + exp := -expon_base; + when pos_denormal | neg_denormal => + if denormalize then + exp := -expon_base; + fract (fraction_width) := '0'; + else + exp := -expon_base - 1; + fract (fraction_width) := '1'; + end if; + when pos_normal | neg_normal | pos_inf | neg_inf => + fract (fraction_width) := '1'; + exp := to_01(SIGNED(arg(exponent_width-1 downto 0)), 'X'); + exp (exponent_width-1) := not exp(exponent_width-1); + when others => + assert NO_WARNING + report "FLOAT_GENERIC_PKG.BREAK_NUMBER: " & + "Meta state detected in fp_break_number process" + severity warning; + -- complete the case, if a meta state goes in, a meta state comes out. + exp := (others => '1'); + fract (fraction_width) := '1'; + end case breakcase; + expon := exp; + end procedure break_number; + + procedure break_number ( + arg : in float; + denormalize : in BOOLEAN := float_denormalize; + check_error : in BOOLEAN := float_check_error; + fract : out ufixed; -- 1 downto -fraction_width + expon : out SIGNED; -- exponent_width-1 downto 0 + sign : out STD_ULOGIC) is + constant fraction_width : NATURAL := -minx(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : NATURAL := arg'high; -- length of FP output exponent + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable fptyp : valid_fpstate; + variable exp : SIGNED (expon'range); + begin + fptyp := Class (arg, check_error); + for i in -1 downto -fraction_width loop + fract(i) := arg(i); + end loop; + sign := to_x01(arg(arg'high)); + breakcase : case fptyp is + when pos_zero | neg_zero => + fract (0) := '0'; + exp := -expon_base; + when pos_denormal | neg_denormal => + if denormalize then + exp := -expon_base; + fract (0) := '0'; + else + exp := -expon_base - 1; + fract (0) := '1'; + end if; + when pos_normal | neg_normal | pos_inf | neg_inf => + fract (0) := '1'; + exp := to_01(SIGNED(arg(exponent_width-1 downto 0)), 'X'); + exp (exponent_width-1) := not exp(exponent_width-1); + when others => + assert NO_WARNING + report "FLOAT_GENERIC_PKG.BREAK_NUMBER: " & + "Meta state detected in fp_break_number process" + severity warning; + -- complete the case, if a meta state goes in, a meta state comes out. + exp := (others => '1'); + fract (0) := '1'; + end case breakcase; + expon := exp; + end procedure break_number; + + -- Arithmetic functions + -- Synthisable + function "abs" ( + arg : float) -- floating point input + return float is + variable result : float (arg'range); -- result + begin + if (arg'length > 0) then + result := to_01 (arg, 'X'); + result (arg'high) := '0'; -- set the sign bit to positive + return result; + else + return NAFP; + end if; + end function "abs"; + + -- IEEE 754 "negative" function + -- Synthisable + function "-" ( + arg : float) -- floating point input + return float is + variable result : float (arg'range); -- result + begin + if (arg'length > 0) then + result := to_01 (arg, 'X'); + result (arg'high) := not result (arg'high); -- invert sign bit + return result; + else + return NAFP; + end if; + end function "-"; + + -- Synthisable + function add ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + constant addguard : NATURAL := guard; -- add one guard bit + variable lfptype, rfptype : valid_fpstate; + variable fpresult : float (exponent_width downto -fraction_width); + variable fractl, fractr : UNSIGNED(fraction_width+1+addguard downto 0); -- fractions + variable fractc, fracts : UNSIGNED (fractl'range); -- constant and shifted variables + variable urfract, ulfract : UNSIGNED (fraction_width downto 0); + variable ufract : UNSIGNED (fraction_width+1+addguard downto 0); + variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED(exponent_width downto 0); -- result exponent + variable shiftx : SIGNED(exponent_width downto 0); -- shift fractions + variable sign : STD_ULOGIC; -- sign of the output + variable leftright : BOOLEAN; -- left or right used + variable lresize, rresize : float (exponent_width downto -fraction_width); + variable sticky : STD_ULOGIC; -- Holds precision for rounding + begin -- addition + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + end if; + if (lfptype = isx or rfptype = isx) then + fpresult := (others => 'X'); + elsif (lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan) + -- Return quiet NAN, IEEE754-1985-7.1,1 + or (lfptype = pos_inf and rfptype = neg_inf) + or (lfptype = neg_inf and rfptype = pos_inf) then + -- Return quiet NAN, IEEE754-1985-7.1,2 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = pos_inf or rfptype = pos_inf) then -- x + inf = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = neg_inf or rfptype = neg_inf) then -- x - inf = -inf + fpresult := neg_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := class (lresize, false); -- errors already checked + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := class (rresize, false); -- errors already checked + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => ulfract, + expon => exponl); + fractl := (others => '0'); + fractl (fraction_width+addguard downto addguard) := ulfract; + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => urfract, + expon => exponr); + fractr := (others => '0'); + fractr (fraction_width+addguard downto addguard) := urfract; + shiftx := (exponl(exponent_width-1) & exponl) - exponr; + if shiftx < -fractl'high then + rexpon := exponr(exponent_width-1) & exponr; + fractc := fractr; + fracts := (others => '0'); -- add zero + leftright := false; + sticky := or_reducex (fractl); + elsif shiftx < 0 then + shiftx := - shiftx; + fracts := shift_right (fractl, to_integer(shiftx)); + fractc := fractr; + rexpon := exponr(exponent_width-1) & exponr; + leftright := false; +-- sticky := or_reducex (fractl (to_integer(shiftx) downto 0)); + sticky := smallfract (fractl, to_integer(shiftx)); + elsif shiftx = 0 then + rexpon := exponl(exponent_width-1) & exponl; + sticky := '0'; + if fractr > fractl then + fractc := fractr; + fracts := fractl; + leftright := false; + else + fractc := fractl; + fracts := fractr; + leftright := true; + end if; + elsif shiftx > fractr'high then + rexpon := exponl(exponent_width-1) & exponl; + fracts := (others => '0'); -- add zero + fractc := fractl; + leftright := true; + sticky := or_reducex (fractr); + elsif shiftx > 0 then + fracts := shift_right (fractr, to_integer(shiftx)); + fractc := fractl; + rexpon := exponl(exponent_width-1) & exponl; + leftright := true; +-- sticky := or_reducex (fractr (to_integer(shiftx) downto 0)); + sticky := smallfract (fractr, to_integer(shiftx)); + end if; + -- add + fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB + if l(l'high) = r(r'high) then + ufract := fractc + fracts; + sign := l(l'high); + else -- signs are different + ufract := fractc - fracts; -- always positive result + if leftright then -- Figure out which sign to use + sign := l(l'high); + else + sign := r(r'high); + end if; + end if; + -- normalize + fpresult := normalize (fract => ufract, + expon => rexpon, + sign => sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => addguard); + end if; + return fpresult; + end function add; + + -- Calls "add". + -- Synthisable + function subtract ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + variable negr : float (r'range); -- negative version of r + begin + negr := -r; -- r := -r + return add (l => l, + r => negr, + round_style => round_style, + guard => guard, + check_error => check_error, + denormalize => denormalize); + end function subtract; + + function multiply ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + constant multguard : NATURAL := guard; -- guard bits + variable lfptype, rfptype : valid_fpstate; + variable fpresult : float (exponent_width downto -fraction_width); + variable fractl, fractr : UNSIGNED(fraction_width downto 0); -- fractions + variable rfract : UNSIGNED((2*(fraction_width))+1 downto 0); -- result fraction + variable sfract : UNSIGNED(fraction_width+1+multguard downto 0); -- result fraction + variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED(exponent_width downto 0); -- result exponent + variable fp_sign : STD_ULOGIC; -- sign of result + variable lresize, rresize : float (exponent_width downto -fraction_width); + variable sticky : STD_ULOGIC; -- Holds precision for rounding + begin -- multiply + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + end if; + if (lfptype = isx or rfptype = isx) then + fpresult := (others => 'X'); + elsif ((lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan)) then + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (((lfptype = pos_inf or lfptype = neg_inf) and + (rfptype = pos_zero or rfptype = neg_zero)) or + ((rfptype = pos_inf or rfptype = neg_inf) and + (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf + -- Return quiet NAN, IEEE754-1985-7.1,3 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = pos_inf or rfptype = pos_inf + or lfptype = neg_inf or rfptype = neg_inf) then -- x * inf = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + -- figure out the sign + fpresult (exponent_width) := l(l'high) xor r(r'high); + else + fp_sign := l(l'high) xor r(r'high); -- figure out the sign + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := class (lresize, false); -- errors already checked + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := class (rresize, false); -- errors already checked + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => fractl, + expon => exponl); + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => fractr, + expon => exponr); + -- multiply + rfract := fractl * fractr; -- Multiply the fraction + sfract := rfract (rfract'high downto + rfract'high - (fraction_width+1+multguard)); + sticky := or_reducex(rfract (rfract'high-(fraction_width+1+multguard) + downto 0)); + -- add the exponents + rexpon := (exponl(exponl'high)&exponl) + (exponr(exponr'high)&exponr) +1; + -- normalize + fpresult := normalize (fract => sfract, + expon => rexpon, + sign => fp_sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => multguard); + end if; + return fpresult; + end function multiply; + + function short_divide ( + lx, rx : UNSIGNED) + return UNSIGNED is + -- This is a special divider for the floating point routies. + -- For a true unsigned divider, "stages" needs to = lx'high + constant stages : INTEGER := lx'high - rx'high; -- number of stages + variable partial : UNSIGNED (lx'range); + variable q : UNSIGNED (stages downto 0); + variable partial_argl : SIGNED (rx'high + 2 downto 0); + variable partial_arg : SIGNED (rx'high + 2 downto 0); + begin + partial := lx; + for i in stages downto 0 loop + partial_argl := resize ("0" & SIGNED (partial(lx'high downto i)), + partial_argl'length); + partial_arg := partial_argl - SIGNED ("0" & rx); + if (partial_arg (partial_arg'high) = '1') then -- negative + q(i) := '0'; + else + q(i) := '1'; + partial (lx'high+i-stages downto lx'high+i-stages-rx'high) := + UNSIGNED (partial_arg(rx'range)); + end if; + end loop; + -- to make the output look like that of the unsigned IEEE divide. + return resize (q, lx'length); + end function short_divide; + + -- 1/X function. Needed for algorithm development. + function reciprocal ( + arg : float; + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := -minx(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : NATURAL := arg'high; -- length of FP output exponent + constant divguard : NATURAL := guard; -- guard bits + function onedivy ( + arg : UNSIGNED) + return UNSIGNED is + variable q : UNSIGNED((2*arg'high)+1 downto 0); + variable one : UNSIGNED (q'range); + begin + one := (others => '0'); + one(one'high) := '1'; + q := short_divide (one, arg); -- Unsiged divide + return resize (q, arg'length+1); + end function onedivy; + variable fptype : valid_fpstate; + variable expon : SIGNED(exponent_width-1 downto 0); -- exponents + variable denorm_offset : NATURAL range 0 to 2; + variable fract : UNSIGNED(fraction_width downto 0); + variable fractg : UNSIGNED(fraction_width+divguard downto 0); + variable sfract : UNSIGNED(fraction_width+1+divguard downto 0); -- result fraction + variable fpresult : float (exponent_width downto -fraction_width); + begin -- reciprocal + fptype := class(arg, check_error); + classcase : case fptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => -- 1/inf, return 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + when neg_zero | pos_zero => -- 1/0 + report "FLOAT_GENERIC_PKG.RECIPROCAL: Floating Point divide by zero" + severity error; + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + when others => + if (fptype = pos_denormal or fptype = neg_denormal) + and ((arg (-1) or arg(-2)) /= '1') then + -- 1/denormal = infinity, with the exception of 2**-expon_base + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + fpresult (exponent_width) := to_x01 (arg (exponent_width)); + else + break_number ( + arg => arg, + fptyp => fptype, + denormalize => denormalize, + fract => fract, + expon => expon); + fractg := (others => '0'); + if (fptype = pos_denormal or fptype = neg_denormal) then + -- The reciprocal of a denormal number is typically zero, + -- execpt for two special cases which are trapped here. + if (to_x01(arg (-1)) = '1') then + fractg (fractg'high downto divguard+1) := + fract (fract'high-1 downto 0); -- Shift to not denormal + denorm_offset := 1; -- add 1 to exponent compensate + else -- arg(-2) = '1' + fractg (fractg'high downto divguard+2) := + fract (fract'high-2 downto 0); -- Shift to not denormal + denorm_offset := 2; -- add 2 to exponent compensate + end if; + else + fractg (fractg'high downto divguard) := fract; + denorm_offset := 0; + end if; + expon := - expon - 3 + denorm_offset; + sfract := onedivy (fractg); + -- normalize + fpresult := normalize (fract => sfract, + expon => expon, + sign => arg(exponent_width), + sticky => '1', + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => divguard); + end if; + end case classcase; + return fpresult; + end function reciprocal; + + -- Synthisable + function divide ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + constant divguard : NATURAL := guard; -- division guard bits + variable lfptype, rfptype : valid_fpstate; + variable fpresult : float (exponent_width downto -fraction_width); + variable ulfract, urfract : UNSIGNED (fraction_width downto 0); +-- variable fractl : unsigned((2*(fraction_width+1)+divguard+2) downto 0); -- left + variable fractl : UNSIGNED((2*(fraction_width+divguard)+1) downto 0); -- left + variable fractr : UNSIGNED(fraction_width+divguard downto 0); -- right + variable rfract : UNSIGNED(fractl'range); -- result fraction + variable sfract : UNSIGNED(fraction_width+1+divguard downto 0); -- result fraction + variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED(exponent_width downto 0); -- result exponent + variable fp_sign : STD_ULOGIC; -- sign of result + variable shifty : INTEGER; -- denormal number shift + variable lresize, rresize : float (exponent_width downto -fraction_width); + begin -- divide + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + end if; + classcase : case rfptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => + if lfptype = pos_inf or lfptype = neg_inf -- inf / inf + or lfptype = quiet_nan or lfptype = nan then + -- Return quiet NAN, IEEE754-1985-7.1,4 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + else -- x / inf = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + end if; + when pos_zero | neg_zero => + if lfptype = pos_zero or lfptype = neg_zero -- 0 / 0 + or lfptype = quiet_nan or lfptype = nan then + -- Return quiet NAN, IEEE754-1985-7.1,4 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + report "FLOAT_GENERIC_PKG.DIVIDE: Floating Point divide by zero" + severity error; + -- Infinity, define in 754-1985-7.2 + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + end if; + when others => + fp_sign := l(l'high) xor r(r'high); -- sign + classcase2 : case lfptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => -- inf / x = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + fpresult(exponent_width) := fp_sign; + when pos_zero | neg_zero => -- 0 / X = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + when others => + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := class (lresize, false); -- errors already checked + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := class (rresize, false); -- errors already checked + fractl := (others => '0'); + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => ulfract, + expon => exponl); + fractl (fractl'high downto fractl'high-fraction_width) := ulfract; + -- right side + fractr := (others => '0'); + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => urfract, + expon => exponr); + fractr (fraction_width+divguard downto divguard) := urfract; + rexpon := (exponl(exponl'high)&exponl) + - (exponr(exponr'high)&exponr) - 2; + if (rfptype = pos_denormal or rfptype = neg_denormal) then + -- Do the shifting here not after. That way we have a smaller + -- shifter, and need a smaller divider, because the top + -- bit in the divisor will always be a "1". + shifty := fraction_width - find_msb(urfract, '1'); + fractr := shift_left (fractr, shifty); + rexpon := rexpon + shifty; + end if; + -- divide + rfract := short_divide (fractl, fractr); -- unsigned divide + sfract := rfract (sfract'range); -- lower bits + -- normalize + fpresult := normalize (fract => sfract, + expon => rexpon, + sign => fp_sign, + sticky => '1', + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => divguard); + end case classcase2; + end case classcase; + return fpresult; + end function divide; + + -- division by a power of 2 + function dividebyp2 ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable fpresult : float (exponent_width downto -fraction_width); + variable ulfract, urfract : UNSIGNED (fraction_width downto 0); + variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED(exponent_width downto 0); -- result exponent + variable fp_sign : STD_ULOGIC; -- sign of result + variable lresize, rresize : float (exponent_width downto -fraction_width); + begin -- divisionbyp2 + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + end if; + classcase : case rfptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => + if lfptype = pos_inf or lfptype = neg_inf then -- inf / inf + -- Return quiet NAN, IEEE754-1985-7.1,4 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + else -- x / inf = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + end if; + when pos_zero | neg_zero => + if lfptype = pos_zero or lfptype = neg_zero then -- 0 / 0 + -- Return quiet NAN, IEEE754-1985-7.1,4 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + report "FLOAT_GENERIC_PKG.DIVIDEBYP2: Floating Point divide by zero" + severity error; + -- Infinity, define in 754-1985-7.2 + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + end if; + when others => + classcase2 : case lfptype is + when isx => + fpresult := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf | neg_inf => -- inf / x = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + fpresult(exponent_width) := l(exponent_width) xor r(exponent_width); + when pos_zero | neg_zero => -- 0 / X = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + when others => + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := class (lresize, false); -- errors already checked + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := class (rresize, false); -- errors already checked + fp_sign := l(l'high) xor r(r'high); -- sign + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => ulfract, + expon => exponl); + -- right side + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => urfract, + expon => exponr); + assert (or_reducex (urfract (fraction_width-1 downto 0)) = '0') + report "FLOAT_GENERIC_PKG.DIVIDEBYP2: " + & "Divideby2 called with a none power of two denominator" + severity error; + rexpon := (exponl(exponl'high)&exponl) + - (exponr(exponr'high)&exponr) - 1; + -- normalize + fpresult := normalize (fract => ulfract, + expon => rexpon, + sign => fp_sign, + sticky => '1', + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => 0); + end case classcase2; + end case classcase; + return fpresult; + end function dividebyp2; + +-- Multiply accumumlate result = l*r + c + function mac ( + l, r, c : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := + -minx (minx(l'low, r'low), c'low); -- length of FP output fraction + constant exponent_width : NATURAL := + maximum (maximum(l'high, r'high), c'high); -- length of FP output exponent + variable lfptype, rfptype, cfptype : valid_fpstate; + variable fpresult : float (exponent_width downto -fraction_width); + variable fractl, fractr : UNSIGNED(fraction_width downto 0); -- fractions + variable fractx : UNSIGNED (fraction_width+guard downto 0); + variable fractc, fracts : UNSIGNED (fraction_width+1+guard downto 0); + variable rfract : UNSIGNED((2*(fraction_width))+1 downto 0); -- result fraction + variable sfract, ufract : UNSIGNED(fraction_width+1+guard downto 0); -- result fraction + variable exponl, exponr, exponc : SIGNED(exponent_width-1 downto 0); -- exponents + variable shiftx : SIGNED(exponent_width downto 0); -- shift fractions + variable rexpon, rexpon2 : SIGNED(exponent_width downto 0); -- result exponent + variable fp_sign : STD_ULOGIC; -- sign of result + variable lresize, rresize : float (exponent_width downto -fraction_width); + variable cresize : float (exponent_width downto -fraction_width - guard); + variable leftright : BOOLEAN; -- left or right used + variable sticky : STD_ULOGIC; -- Holds precision for rounding + begin -- multiply + if (fraction_width = 0 or l'length < 7 or r'length < 7 or c'length < 7) then + lfptype := isx; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + cfptype := class (c, check_error); + end if; + if (lfptype = isx or rfptype = isx or cfptype = isx) then + fpresult := (others => 'X'); + elsif (lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan or + cfptype = nan or cfptype = quiet_nan) then + -- Return quiet NAN, IEEE754-1985-7.1,1 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (((lfptype = pos_inf or lfptype = neg_inf) and + (rfptype = pos_zero or rfptype = neg_zero)) or + ((rfptype = pos_inf or rfptype = neg_inf) and + (lfptype = pos_zero or lfptype = neg_zero))) then -- 0 * inf + -- Return quiet NAN, IEEE754-1985-7.1,3 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (lfptype = pos_inf or rfptype = pos_inf + or lfptype = neg_inf or rfptype = neg_inf -- x * inf = inf + or cfptype = neg_inf or cfptype = pos_inf) then -- x + inf = inf + fpresult := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + -- figure out the sign + fpresult (exponent_width) := l(l'high) xor r(r'high); + else + fp_sign := l(l'high) xor r(r'high); -- figure out the sign + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := class (lresize, false); -- errors already checked + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := class (rresize, false); -- errors already checked + cresize := resize (arg => c, + exponent_width => exponent_width, + fraction_width => -cresize'low, + denormalize_in => denormalize, + denormalize => denormalize); + cfptype := class (cresize, false); -- errors already checked + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => fractl, + expon => exponl); + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => fractr, + expon => exponr); + break_number ( + arg => cresize, + fptyp => cfptype, + denormalize => denormalize, + fract => fractx, + expon => exponc); + + -- multiply + rfract := fractl * fractr; -- Multiply the fraction + -- add the exponents + rexpon := (exponl(exponl'high)&exponl) + (exponr(exponr'high)&exponr) +1; + shiftx := rexpon - exponc; + if shiftx < -fractl'high then + rexpon2 := exponc(exponent_width-1) & exponc; + fractc := "0" & fractx; + fracts := (others => '0'); + sticky := or_reducex (rfract); + elsif shiftx < 0 then + shiftx := - shiftx; + fracts := shift_right (rfract (rfract'high downto rfract'high + - fracts'length+1), + to_integer(shiftx)); + fractc := "0" & fractx; + rexpon2 := exponc(exponent_width-1) & exponc; + leftright := false; + sticky := or_reducex (rfract (to_integer(shiftx)+rfract'high + - fracts'length downto 0)); + elsif shiftx = 0 then + rexpon2 := exponc(exponent_width-1) & exponc; + sticky := or_reducex (rfract (rfract'high - fractc'length downto 0)); + if rfract (rfract'high downto rfract'high - fractc'length+1) > fractx + then + fractc := "0" & fractx; + fracts := rfract (rfract'high downto rfract'high + - fracts'length+1); + leftright := false; + else + fractc := rfract (rfract'high downto rfract'high + - fractc'length+1); + fracts := "0" & fractx; + leftright := true; + end if; + elsif shiftx > fractx'high then + rexpon2 := rexpon; + fracts := (others => '0'); + fractc := rfract (rfract'high downto rfract'high - fractc'length+1); + leftright := true; + sticky := or_reducex (fractx & rfract (rfract'high - fractc'length + downto 0)); + else -- fractx'high > shiftx > 0 + rexpon2 := rexpon; + fracts := "0" & shift_right (fractx, to_integer (shiftx)); + fractc := rfract (rfract'high downto rfract'high - fractc'length+1); + leftright := true; + sticky := or_reducex (fractx (to_integer (shiftx) downto 0) + & rfract (rfract'high - fractc'length downto 0)); + end if; + fracts (0) := fracts (0) or sticky; -- Or the sticky bit into the LSB + if fp_sign = to_X01(c(c'high)) then + ufract := fractc + fracts; + fp_sign := fp_sign; + else -- signs are different + ufract := fractc - fracts; -- always positive result + if leftright then -- Figure out which sign to use + fp_sign := fp_sign; + else + fp_sign := c(c'high); + end if; + end if; + -- normalize + fpresult := normalize (fract => ufract, + expon => rexpon2, + sign => fp_sign, + sticky => sticky, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => guard); + end if; + return fpresult; + end function mac; + + function remainder ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + constant divguard : NATURAL := guard; -- division guard bits + variable lfptype, rfptype : valid_fpstate; + variable fpresult : float (exponent_width downto -fraction_width); + variable ulfract, urfract : UNSIGNED (fraction_width downto 0); + variable fractr, fractl : UNSIGNED(fraction_width+divguard downto 0); -- right + variable rfract : UNSIGNED(fractr'range); -- result fraction + variable sfract : UNSIGNED(fraction_width+divguard downto 0); -- result fraction + variable exponl, exponr : SIGNED(exponent_width-1 downto 0); -- exponents + variable rexpon : SIGNED(exponent_width downto 0); -- result exponent + variable fp_sign : STD_ULOGIC; -- sign of result + variable shifty : INTEGER; -- denormal number shift + variable lresize, rresize : float (exponent_width downto -fraction_width); + begin -- remainder + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + end if; + if (lfptype = isx or rfptype = isx) then + fpresult := (others => 'X'); + elsif (lfptype = nan or lfptype = quiet_nan) + or (rfptype = nan or rfptype = quiet_nan) + -- Return quiet NAN, IEEE754-1985-7.1,1 + or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x + -- Return quiet NAN, IEEE754-1985-7.1,5 + or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0 + -- Return quiet NAN, IEEE754-1985-7.1,5 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (abs(l) < abs(r)) then + fpresult := l; + else + fp_sign := to_X01(l(l'high)); -- sign + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + lfptype := class (lresize, false); -- errors already checked + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rfptype := class (rresize, false); -- errors already checked + fractl := (others => '0'); + break_number ( + arg => lresize, + fptyp => lfptype, + denormalize => denormalize, + fract => ulfract, + expon => exponl); + fractl (fraction_width+divguard downto divguard) := ulfract; + -- right side + fractr := (others => '0'); + break_number ( + arg => rresize, + fptyp => rfptype, + denormalize => denormalize, + fract => urfract, + expon => exponr); + fractr (fraction_width+divguard downto divguard) := urfract; + rexpon := (exponr(exponr'high)&exponr); + shifty := to_integer(exponl - rexpon); + if (shifty > 0) then + fractr := shift_right (fractr, shifty); + rexpon := rexpon + shifty; + end if; + if (fractr /= 0) then + -- rem + rfract := fractl rem fractr; -- unsigned rem + sfract := rfract (sfract'range); -- lower bits + -- normalize + fpresult := normalize (fract => sfract, + expon => rexpon, + sign => fp_sign, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => divguard); + else + -- If we shift "fractr" so far that it becomes zero, return zero. + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + end if; + end if; + return fpresult; + end function remainder; + + function modulo ( + l, r : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant guard : NATURAL := float_guard_bits; -- number of guard bits + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := - minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable fpresult : float (exponent_width downto -fraction_width); + variable remres : float (exponent_width downto -fraction_width); + begin -- remainder + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + lfptype := isx; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + end if; + if (lfptype = isx or rfptype = isx) then + fpresult := (others => 'X'); + elsif (lfptype = nan or lfptype = quiet_nan) + or (rfptype = nan or rfptype = quiet_nan) + -- Return quiet NAN, IEEE754-1985-7.1,1 + or (lfptype = pos_inf or lfptype = neg_inf) -- inf rem x + -- Return quiet NAN, IEEE754-1985-7.1,5 + or (rfptype = pos_zero or rfptype = neg_zero) then -- x rem 0 + -- Return quiet NAN, IEEE754-1985-7.1,5 + fpresult := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (rfptype = pos_inf or rfptype = neg_inf) then -- x rem inf = 0 + fpresult := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + remres := remainder (l => abs(l), + r => abs(r), + round_style => round_style, + guard => guard, + check_error => false, + denormalize => denormalize); + -- MOD is the same as REM, but you do something different with + -- negative values + if (is_negative (l)) then + remres := - remres; + end if; + if (is_negative (l) = is_negative (r) or remres = 0) then + fpresult := remres; + else + fpresult := add (l => remres, + r => r, + round_style => round_style, + guard => guard, + check_error => false, + denormalize => denormalize); + end if; + end if; + return fpresult; + end function modulo; + + function Is_Negative (arg : float) return BOOLEAN is + begin + return (to_x01(arg(arg'high)) = '1'); + end function Is_Negative; + + -- compare functions + -- =, /=, >=, <=, <, > + + -- Synthisable + function eq ( -- equal = + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + variable lfptype, rfptype : valid_fpstate; + variable is_equal, is_unordered : BOOLEAN; + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lresize, rresize : float (exponent_width downto -fraction_width); + begin -- equal + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return false; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + end if; + if (lfptype = neg_zero or lfptype = pos_zero) and + (rfptype = neg_zero or rfptype = pos_zero) then + is_equal := true; + else + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + is_equal := (to_slv(lresize) = to_slv(rresize)); + end if; + if (check_error) then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return is_equal and not is_unordered; + end function eq; + + -- Synthisable + function lt ( -- less than < + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable expl, expr : UNSIGNED (exponent_width-1 downto 0); + variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0); + variable is_less_than, is_unordered : BOOLEAN; + variable lresize, rresize : float (exponent_width downto -fraction_width); + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + is_less_than := false; + else + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits + expl := to_01(UNSIGNED(lresize(exponent_width-1 downto 0)), 'X'); + expr := to_01(UNSIGNED(rresize(exponent_width-1 downto 0)), 'X'); + if expl = expr then + fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width))); + fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width))); + if to_x01(l(l'high)) = '0' then -- positive number + is_less_than := (fractl < fractr); + else + is_less_than := (fractl > fractr); -- negative + end if; + else + if to_x01(l(l'high)) = '0' then -- positive number + is_less_than := (expl < expr); + else + is_less_than := (expl > expr); -- negative + end if; + end if; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + if (lfptype = neg_zero and rfptype = pos_zero) then + is_less_than := false; -- -0 < 0 returns false. + else + is_less_than := (to_x01(l(l'high)) > to_x01(r(r'high))); + end if; + end if; + end if; + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return is_less_than and not is_unordered; + end function lt; + + -- Synthisable + function gt ( -- greater than > + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lfptype, rfptype : valid_fpstate; + variable expl, expr : UNSIGNED (exponent_width-1 downto 0); + variable fractl, fractr : UNSIGNED (fraction_width-1 downto 0); + variable is_greater_than : BOOLEAN; + variable is_unordered : BOOLEAN; + variable lresize, rresize : float (exponent_width downto -fraction_width); + begin -- greater_than + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + is_greater_than := false; + else + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => denormalize, + denormalize => denormalize); + if to_x01(l(l'high)) = to_x01(r(r'high)) then -- sign bits + expl := to_01(UNSIGNED(lresize(exponent_width-1 downto 0)), 'X'); + expr := to_01(UNSIGNED(rresize(exponent_width-1 downto 0)), 'X'); + if expl = expr then + fractl := UNSIGNED (to_slv(lresize(-1 downto -fraction_width))); + fractr := UNSIGNED (to_slv(rresize(-1 downto -fraction_width))); + if to_x01(l(l'high)) = '0' then -- positive number + is_greater_than := fractl > fractr; + else + is_greater_than := fractl < fractr; -- negative + end if; + else + if to_x01(l(l'high)) = '0' then -- positive number + is_greater_than := expl > expr; + else + is_greater_than := expl < expr; -- negative + end if; + end if; + else + lfptype := class (l, check_error); + rfptype := class (r, check_error); + if (lfptype = pos_zero and rfptype = neg_zero) then + is_greater_than := false; -- 0 > -0 returns false. + else + is_greater_than := to_x01(l(l'high)) < to_x01(r(r'high)); + end if; + end if; + end if; + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return is_greater_than and not is_unordered; + end function gt; + + -- purpose: /= function + function ne ( -- not equal /= + l, r : float; + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + variable is_equal, is_unordered : BOOLEAN; + begin + is_equal := eq (l => l, + r => r, + check_error => false, + denormalize => denormalize); + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return not (is_equal and not is_unordered); + end function ne; + + function le ( -- less than or equal to <= + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + variable is_greater_than, is_unordered : BOOLEAN; + begin + is_greater_than := gt (l => l, + r => r, + check_error => false, + denormalize => denormalize); + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return not is_greater_than and not is_unordered; + end function le; + + function ge ( -- greather than or equal to >= + l, r : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; + constant denormalize : BOOLEAN := float_denormalize) + return BOOLEAN is + variable is_less_than, is_unordered : BOOLEAN; + begin + is_less_than := lt (l => l, + r => r, + check_error => false, + denormalize => denormalize); + if check_error then + is_unordered := Unordered (x => l, + y => r); + else + is_unordered := false; + end if; + return not is_less_than and not is_unordered; + end function ge; + + --%%% Uncomment the following function +-- function "?=" (L, R: float) return std_ulogic is + function \?=\ (L, R : float) return STD_ULOGIC is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lresize, rresize : float (exponent_width downto -fraction_width); + begin -- ?= + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + else + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => float_denormalize, + denormalize => float_denormalize); + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => float_denormalize, + denormalize => float_denormalize); + return \?=\ (ufixed(lresize), ufixed(rresize)); + --%%% return (to_slv(lresize) ?= to_slv(rresize)); + end if; + end function \?=\; + --%%% end function "?="; + + function \?/=\ (L, R : float) return STD_ULOGIC is + constant fraction_width : NATURAL := -minx(l'low, r'low); -- length of FP output fraction + constant exponent_width : NATURAL := maximum(l'high, r'high); -- length of FP output exponent + variable lresize, rresize : float (exponent_width downto -fraction_width); + begin -- ?/= + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + else + lresize := resize (arg => l, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => float_denormalize, + denormalize => float_denormalize); + rresize := resize (arg => r, + exponent_width => exponent_width, + fraction_width => fraction_width, + denormalize_in => float_denormalize, + denormalize => float_denormalize); + return \?/=\ (ufixed(lresize), ufixed(rresize)); + --%%% return (to_slv(lresize) ?/= to_slv(rresize)); + end if; + end function \?/=\; + --%%% end function "?/="; + + -- %%% function "?>" (L, R : float) return std_ulogic is + function \?>\ (L, R : float) return std_ulogic is + constant fraction_width : NATURAL := -minx(l'low, r'low); + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) + or (find_msb (r, '-') /= r'low-1) then + report "float_generic_pkg.""?>"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l > r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>\; + -- %%% end function "?>"; + + -- %%% function "?>=" (L, R : float) return std_ulogic is + function \?>=\ (L, R : float) return std_ulogic is + constant fraction_width : NATURAL := -minx(l'low, r'low); + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) + or (find_msb (r, '-') /= r'low-1) then + report "float_generic_pkg.""?>="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l >= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?>=\; + -- %%% end function "?>="; + + -- %%% function "?<" (L, R : float) return std_ulogic is + function \?<\ (L, R : float) return std_ulogic is + constant fraction_width : NATURAL := -minx(l'low, r'low); + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) + or (find_msb (r, '-') /= r'low-1) then + report "float_generic_pkg.""?<"": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l < r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<\; + -- %%% end function "?<"; + + -- %%% function "?<=" (L, R : float) return std_ulogic is + function \?<=\ (L, R : float) return std_ulogic is + constant fraction_width : NATURAL := -minx(l'low, r'low); + begin + if (fraction_width = 0 or l'length < 7 or r'length < 7) then + return 'X'; + elsif (find_msb (l, '-') /= l'low-1) + or (find_msb (r, '-') /= r'low-1) then + report "float_generic_pkg.""?<="": '-' found in compare string" + severity error; + return 'X'; + else + if is_x(l) or is_x(r) then + return 'X'; + elsif l <= r then + return '1'; + else + return '0'; + end if; + end if; + end function \?<=\; + -- %%% end function "?<="; + + function std_match (L, R : float) return BOOLEAN is + begin + return std_match(to_slv(L), to_slv(R)); + end function std_match; + + function find_lsb (arg : float; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'low to arg'high loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'high+1; -- return out of bounds 'high + end function find_lsb; + + function find_msb (arg : float; y : STD_ULOGIC) return INTEGER is + begin + for_loop : for i in arg'high downto arg'low loop + if arg(i) = y then + return i; + end if; + end loop; + return arg'low-1; -- return out of bounds 'low + end function find_msb; + + -- These override the defaults for the compare operators. + function "=" (l, r : float) return BOOLEAN is + begin + return eq(l, r); + end function "="; + function "/=" (l, r : float) return BOOLEAN is + begin + return ne(l, r); + end function "/="; + function ">=" (l, r : float) return BOOLEAN is + begin + return ge(l, r); + end function ">="; + function "<=" (l, r : float) return BOOLEAN is + begin + return le(l, r); + end function "<="; + function ">" (l, r : float) return BOOLEAN is + begin + return gt(l, r); + end function ">"; + function "<" (l, r : float) return BOOLEAN is + begin + return lt(l, r); + end function "<"; + -- purpose: maximum of two numbers (overrides default) + function maximum ( + L, R : float) + return float is + begin + if l > r then return l; + else return r; + end if; + end function maximum; + + function minimum ( + L, R : float) + return float is + begin + if l > r then return r; + else return l; + end if; + end function minimum; + + ----------------------------------------------------------------------------- + -- conversion functions + ----------------------------------------------------------------------------- + + -- Converts a floating point number of one format into another format + -- Synthesizable + function resize ( + arg : float; -- Floating point input + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant in_fraction_width : NATURAL := -arg'low; -- length of FP output fraction + constant in_exponent_width : NATURAL := arg'high; -- length of FP output exponent + variable result : float (exponent_width downto -fraction_width); + -- result value + variable fptype : valid_fpstate; + variable expon_in : SIGNED (in_exponent_width-1 downto 0); + variable fract_in : UNSIGNED (in_fraction_width downto 0); + variable round : BOOLEAN; + variable expon_out : SIGNED (exponent_width-1 downto 0); -- output fract + variable fract_out : UNSIGNED (fraction_width downto 0); -- output fract + variable passguard : NATURAL; + begin + fptype := class(arg, check_error); + if ((fptype = pos_denormal or fptype = neg_denormal) and denormalize_in + and (in_exponent_width < exponent_width + or in_fraction_width < fraction_width)) + or in_exponent_width > exponent_width + or in_fraction_width > fraction_width then + -- size reduction + classcase : case fptype is + when isx => + result := (others => 'X'); + when nan | quiet_nan => + result := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_inf => + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + when neg_inf => + result := neg_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + when pos_zero | neg_zero => + result := zerofp (fraction_width => fraction_width, -- hate -0 + exponent_width => exponent_width); + when others => + break_number ( + arg => arg, + fptyp => fptype, + denormalize => denormalize_in, + fract => fract_in, + expon => expon_in); + if fraction_width > in_fraction_width and denormalize_in then + -- You only get here if you have a denormal input + fract_out := (others => '0'); -- pad with zeros + fract_out (fraction_width downto + fraction_width - in_fraction_width) := fract_in; + result := normalize ( + fract => fract_out, + expon => expon_in, + sign => arg(arg'high), + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => 0); + else + result := normalize ( + fract => fract_in, + expon => expon_in, + sign => arg(arg'high), + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => in_fraction_width - fraction_width); + end if; + end case classcase; + else -- size increase or the same size + if exponent_width > in_exponent_width then + expon_in := signed(arg (in_exponent_width-1 downto 0)); + if fptype = pos_zero or fptype = neg_zero then + result (exponent_width-1 downto 0) := (others => '0'); + elsif expon_in = -1 then -- inf or nan (shorts out check_error) + result (exponent_width-1 downto 0) := (others => '1'); + else + -- invert top BIT + expon_in(expon_in'high) := not expon_in(expon_in'high); + expon_out := resize (expon_in, expon_out'length); -- signed expand + -- Flip it back. + expon_out(expon_out'high) := not expon_out(expon_out'high); + result (exponent_width-1 downto 0) := float(expon_out); + end if; + result (exponent_width) := arg (in_exponent_width); -- sign + else -- exponent_width = in_exponent_width + result (exponent_width downto 0) := arg (in_exponent_width downto 0); + end if; + if fraction_width > in_fraction_width then + result (-1 downto -fraction_width) := (others => '0'); -- zeros + result (-1 downto -in_fraction_width) := + arg (-1 downto -in_fraction_width); + else -- fraction_width = in_fraciton_width + result (-1 downto -fraction_width) := + arg (-1 downto -in_fraction_width); + end if; + end if; + return result; + end function resize; + + function resize ( + arg : float; -- Floating point input + size_res : float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := resize (arg => arg, + fraction_width => -size_res'low, + exponent_width => size_res'high, + round_style => round_style, + check_error => check_error, + denormalize_in => denormalize_in, + denormalize => denormalize); + return result; + end if; + end function resize; + + function to_float32 ( + arg : float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + begin + return resize (arg => arg, + exponent_width => float32'high, + fraction_width => -float32'low, + round_style => round_style, + check_error => check_error, + denormalize_in => denormalize_in, + denormalize => denormalize); + end function to_float32; + + function to_float64 ( + arg : float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + begin + return resize (arg => arg, + exponent_width => float64'high, + fraction_width => -float64'low, + round_style => round_style, + check_error => check_error, + denormalize_in => denormalize_in, + denormalize => denormalize); + end function to_float64; + + function to_float128 ( + arg : float; + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; + constant denormalize_in : BOOLEAN := float_denormalize; -- Use IEEE extended FP + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + begin + return resize (arg => arg, + exponent_width => float128'high, + fraction_width => -float128'low, + round_style => round_style, + check_error => check_error, + denormalize_in => denormalize_in, + denormalize => denormalize); + end function to_float128; + + -- to_float (Real) + -- Not Synthisable (unless the input is a constant) + function to_float ( + arg : REAL; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + variable result : float (exponent_width downto -fraction_width); + variable arg_real : REAL; -- Real version of argument + variable validfp : boundary_type; -- Check for valid results + variable exp : INTEGER; -- Integer version of exponent + variable exp_real : REAL; -- real version of exponent + variable expon : UNSIGNED (exponent_width - 1 downto 0); + -- Unsigned version of exp. + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable fract : UNSIGNED (fraction_width-1 downto 0); + variable frac : REAL; -- Real version of fraction + constant roundfrac : REAL := 2.0 ** (-2 - fract'high); -- used for rounding + variable round : BOOLEAN; -- to round or not to round + begin + result := (others => '0'); + arg_real := arg; + if arg_real < 0.0 then + result (exponent_width) := '1'; + arg_real := 0.0 - arg_real; -- Make it positive. + else + result (exponent_width) := '0'; + end if; + validfp := test_boundary (arg => arg_real, + fraction_width => fraction_width, + exponent_width => exponent_width, + denormalize => denormalize); + if validfp = zero then + return result; -- Result initialized to "0". + elsif validfp = infinity then + result (exponent_width - 1 downto 0) := (others => '1'); -- Exponent all "1" + -- return infinity. + return result; + else + if validfp = denormal then -- Exponent will default to "0". + expon := (others => '0'); + frac := arg_real * (2.0 ** (to_integer(expon_base)-1)); + else -- Number less than 1. "normal" number +-- exp_real := log (arg_real)/ log (2.0); + exp_real := log2 (arg_real); + exp := INTEGER (floor(exp_real)); -- positive fraction. + expon := UNSIGNED (to_signed (exp-1, exponent_width)); + expon(exponent_width-1) := not expon(exponent_width-1); + frac := (arg_real / 2.0 ** exp) - 1.0; -- Number less than 1. + end if; + for i in 0 to fract'high loop + if frac >= 2.0 ** (-1 - i) then + fract (fract'high - i) := '1'; + frac := frac - 2.0 ** (-1 - i); + else + fract (fract'high - i) := '0'; + end if; + end loop; + round := false; + case round_style is + when round_nearest => + if frac > roundfrac or ((frac = roundfrac) and fract(0) = '1') then + round := true; + end if; + when round_inf => + if frac /= 0.0 and result(exponent_width) = '0' then + round := true; + end if; + when round_neginf => + if frac /= 0.0 and result(exponent_width) = '1' then + round := true; + end if; + when round_zero => + null; -- don't round + end case; + if (round) then + if and_reducex(fract) = '1' then -- fraction is all "1" + expon := expon + 1; + fract := (others => '0'); + else + fract := fract + 1; + end if; + end if; + result (exponent_width-1 downto 0) := float(expon); + result (-1 downto -fraction_width) := float(fract); + return result; + end if; + end function to_float; + + -- to_float (Integer) + -- Synthisable + function to_float ( + arg : INTEGER; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return float is + variable result : float (exponent_width downto -fraction_width); + variable arg_int : INTEGER; -- Real version of argument + variable rexp : SIGNED (exponent_width - 1 downto 0); + variable exp : SIGNED (exponent_width - 1 downto 0); + -- signed version of exp. + variable expon : UNSIGNED (exponent_width - 1 downto 0); + -- Unsigned version of exp. + variable rfract : UNSIGNED (fraction_width-1 downto 0); + variable fract : UNSIGNED (fraction_width-1 downto 0); + variable round : BOOLEAN; + constant frac_base : INTEGER := 30; -- Base to multiply fraction by + variable fract_shift : UNSIGNED (frac_base downto 0); + -- unshifted fract + variable validfp : boundary_type; -- used to check integer + begin + if arg < 0 then + result (exponent_width) := '1'; + arg_int := -arg; -- Make it positive. + else + result (exponent_width) := '0'; + arg_int := arg; + end if; + validfp := fp_input_type (arg => arg_int, + exponent_width => exponent_width, + fraction_width => fraction_width); + if validfp = zero then + result := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif validfp = infinity then + if result (exponent_width) = '0' then + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + -- return infinity. + result := neg_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + end if; + else -- Normal number (can't be denormal) + -- Compute Exponent + exp := to_signed (log2(arg_int), exp'length); -- positive fraction. + -- Compute Fraction + fract_shift := to_unsigned (arg_int, frac_base+1); + fract_shift := shift_left (fract_shift, (frac_base-to_integer(exp))); + -- pull out the fraction + fract := (others => '0'); -- zero out fraction first. + fract (fract'high downto maximum(0, fract'high-(frac_base-1))) := + fract_shift (frac_base-1 downto maximum(0, frac_base-1-fract'high)); + -- Round + if frac_base-1-fract'high > 0 then + round := check_round ( + fract_in => fract (0), + sign => result (exponent_width), + remainder => fract_shift (frac_base-2-fract'high + downto 0), + round_style => round_style); + if round then + fp_round(fract_in => fract, + expon_in => exp, + fract_out => rfract, + expon_out => rexp); + else + rfract := fract; + rexp := exp; + end if; + else + rexp := exp; + rfract := fract; + end if; + expon := UNSIGNED (rexp-1); + expon(exponent_width-1) := not expon(exponent_width-1); + result (exponent_width-1 downto 0) := float(expon); + result (-1 downto -fraction_width) := float(rfract); + end if; + return result; + end function to_float; + + -- to_float (unsigned) + -- Synthesizable + function to_float ( + arg : UNSIGNED; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return float is + variable result : float (exponent_width downto -fraction_width); + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : UNSIGNED(ARG_LEFT downto 0) is ARG; + variable arg_int : UNSIGNED(xarg'range); -- Real version of argument + variable argb2 : UNSIGNED(xarg'high/2 downto 0); -- log2 of input + variable rexp : SIGNED (exponent_width - 1 downto 0); + variable exp : SIGNED (exponent_width - 1 downto 0); + -- signed version of exp. + variable expon : UNSIGNED (exponent_width - 1 downto 0); + -- Unsigned version of exp. + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable round : BOOLEAN; + variable fract : UNSIGNED (fraction_width-1 downto 0); + variable rfract : UNSIGNED (fraction_width-1 downto 0); + begin + arg_int := UNSIGNED(to_x01(STD_LOGIC_VECTOR (xarg))); + if (or_reducex (arg_int) = 'X') then + result := (others => 'X'); + elsif (arg_int = 0) then + result := zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + else -- Normal number (can't be denormal) + result (exponent_width) := '0'; -- positive sign + -- Compute Exponent + argb2 := to_unsigned(find_msb(arg_int, '1'), argb2'length); -- Log2 + if argb2 > UNSIGNED(expon_base) then + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + exp := SIGNED(resize(argb2, exp'length)); + arg_int := shift_left (arg_int, arg_int'high-to_integer(exp)); + if (arg_int'high > fraction_width) then + fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); + round := check_round ( + fract_in => fract (0), + sign => result (exponent_width), + remainder => arg_int((arg_int'high-fraction_width-1) + downto 0), + round_style => round_style); + if round then + fp_round(fract_in => fract, + expon_in => exp, + fract_out => rfract, + expon_out => rexp); + else + rfract := fract; + rexp := exp; + end if; + else + rexp := exp; + rfract := (others => '0'); + rfract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := + arg_int (arg_int'high-1 downto 0); + end if; + expon := UNSIGNED (rexp-1); + expon(exponent_width-1) := not expon(exponent_width-1); + result (exponent_width-1 downto 0) := float(expon); + result (-1 downto -fraction_width) := float(rfract); + end if; + end if; + return result; + end function to_float; + + -- to_float (signed) + -- Synthesizable + function to_float ( + arg : SIGNED; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style) -- rounding option + return float is + constant ARG_LEFT : INTEGER := ARG'length-1; + alias XARG : SIGNED(ARG_LEFT downto 0) is ARG; + variable result : float (exponent_width downto -fraction_width); + variable argabs : SIGNED (xarg'range); + variable arg_int : UNSIGNED(xarg'range); -- unsigned version of argument + variable sign : STD_ULOGIC; -- sign of the signed number + begin + sign := to_x01 (xarg(xarg'high)); + argabs := abs (xarg); + arg_int := UNSIGNED (argabs); + result := to_float ( + arg => arg_int, + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style); + if sign = '1' then + result (exponent_width) := '1'; + end if; + return result; + end function to_float; + + -- std_logic_vector to float + function to_float ( + arg : STD_LOGIC_VECTOR; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction + return float is + variable fpvar : float (exponent_width downto -fraction_width); + alias argslv : STD_LOGIC_VECTOR (fpvar'length-1 downto 0) is arg; + begin + fpvar := float(argslv); +-- floop : for i in fpvar'range loop +-- fpvar(i) := to_X01 (argslv(i-fpvar'low)); -- fpvar(8) := arg (8+23) +-- end loop floop; + return fpvar; + end function to_float; + + -- std_ulogic_vector to float + function to_float ( + arg : STD_ULOGIC_VECTOR; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width) -- length of FP output fraction + return float is + begin + return to_float (arg => to_stdlogicvector(arg), + exponent_width => exponent_width, + fraction_width => fraction_width); + end function to_float; + + -- purpose: converts a ufixed to a floating point + function to_float ( + arg : ufixed; -- unsigned fixed point input + constant exponent_width : NATURAL := float_exponent_width; -- width of exponent + constant fraction_width : NATURAL := float_fraction_width; -- width of fraction + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- use ieee extentions + return float is + constant integer_width : INTEGER := arg'high; + constant in_fraction_width : INTEGER := arg'low; + variable xresult : ufixed (integer_width downto in_fraction_width); + variable result : float (exponent_width downto -fraction_width); + variable arg_int : UNSIGNED(integer_width - in_fraction_width + downto 0); -- Real version of argument + variable exp, exptmp : SIGNED (exponent_width downto 0); + variable expon : UNSIGNED (exponent_width - 1 downto 0); -- Unsigned version of exp. + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable fract, fracttmp : UNSIGNED (fraction_width-1 downto 0) := + (others => '0'); + variable round : BOOLEAN := false; + begin -- function to_float + xresult := to_01(arg, 'X'); + arg_int := UNSIGNED(to_slv(xresult)); + if (or_reducex (arg_int) = 'X') then + result := (others => 'X'); + elsif (arg_int = 0) then + result := (others => '0'); -- return zero + else + result := (others => '0'); -- positive sign + -- Compute Exponent + exp := to_signed(find_msb(arg_int, '1'), exp'length); -- Log2 + if exp + in_fraction_width > expon_base then -- return infinity + result := pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + return result; + elsif (denormalize and + (exp + in_fraction_width <= -resize(expon_base, exp'length))) then + -- denormal number + exp := -resize(expon_base, exp'length); + -- shift by a constant + arg_int := shift_left (arg_int, + (arg_int'high + to_integer(expon_base) + + in_fraction_width - 1)); + if (arg_int'high > fraction_width) then + fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); + round := check_round ( + fract_in => arg_int(arg_int'high-fraction_width), + sign => '0', + remainder => arg_int((arg_int'high-fraction_width-1) + downto 0), + round_style => round_style); + if (round) then + fp_round (fract_in => arg_int (arg_int'high-1 downto + (arg_int'high-fraction_width)), + expon_in => exp, + fract_out => fract, + expon_out => exptmp); + exp := exptmp; + end if; + else + fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := + arg_int (arg_int'high-1 downto 0); + end if; + else + arg_int := shift_left (arg_int, arg_int'high-to_integer(exp)); + exp := exp + in_fraction_width; + if (arg_int'high > fraction_width) then + fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); + round := check_round ( + fract_in => fract(0), + sign => '0', + remainder => arg_int((arg_int'high-fraction_width-1) + downto 0), + round_style => round_style); + if (round) then + fp_round (fract_in => fract, + expon_in => exp, + fract_out => fracttmp, + expon_out => exptmp); + fract := fracttmp; + exp := exptmp; + end if; + else + fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := + arg_int (arg_int'high-1 downto 0); + end if; + end if; + expon := UNSIGNED (resize (exp-1, exponent_width)); + expon(exponent_width-1) := not expon(exponent_width-1); + result (exponent_width-1 downto 0) := float(expon); + result (-1 downto -fraction_width) := float(fract); + end if; + return result; + end function to_float; + + function to_float ( + arg : sfixed; + constant exponent_width : NATURAL := float_exponent_width; -- length of FP output exponent + constant fraction_width : NATURAL := float_fraction_width; -- length of FP output fraction + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- rounding option + return float is + constant integer_width : INTEGER := arg'high; + constant in_fraction_width : INTEGER := arg'low; + variable xresult : sfixed (integer_width downto in_fraction_width); + variable result : float (exponent_width downto -fraction_width); + variable arg_int : UNSIGNED(integer_width - in_fraction_width - 1 + downto 0); -- signed version of argument + variable argx : SIGNED (integer_width - in_fraction_width downto 0); + variable exp, exptmp : SIGNED (exponent_width downto 0); + variable expon : UNSIGNED (exponent_width - 1 downto 0); + -- Unsigned version of exp. + constant expon_base : SIGNED (exponent_width-1 downto 0) := + gen_expon_base(exponent_width); -- exponent offset + variable fract, fracttmp : UNSIGNED (fraction_width-1 downto 0) := + (others => '0'); + variable round : BOOLEAN := false; + begin + xresult := to_01(arg, 'X'); + argx := SIGNED(to_slv(xresult)); + if (or_reducex (UNSIGNED(argx)) = 'X') then + result := (others => 'X'); + elsif (argx = 0) then + result := (others => '0'); + else + result := (others => '0'); -- zero out the result + if argx(argx'left) = '1' then -- toss the sign bit + result (exponent_width) := '1'; -- Negative number + argx := -argx; -- Make it positive. + else + result (exponent_width) := '0'; + end if; + arg_int := UNSIGNED(to_x01(STD_LOGIC_VECTOR (argx(arg_int'range)))); + -- Compute Exponent + exp := to_signed(find_msb(arg_int, '1'), exp'length); -- Log2 + if exp + in_fraction_width > expon_base then -- return infinity + result (-1 downto -fraction_width) := (others => '0'); + result (exponent_width -1 downto 0) := (others => '1'); + return result; + elsif (denormalize and + (exp + in_fraction_width <= -resize(expon_base, exp'length))) then + exp := -resize(expon_base, exp'length); + -- shift by a constant + arg_int := shift_left (arg_int, + (arg_int'high + to_integer(expon_base) + + in_fraction_width - 1)); + if (arg_int'high > fraction_width) then + fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); + round := check_round ( + fract_in => arg_int(arg_int'high-fraction_width), + sign => result(result'high), + remainder => arg_int((arg_int'high-fraction_width-1) + downto 0), + round_style => round_style); + if (round) then + fp_round (fract_in => arg_int (arg_int'high-1 downto + (arg_int'high-fraction_width)), + expon_in => exp, + fract_out => fract, + expon_out => exptmp); + exp := exptmp; + end if; + else + fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := + arg_int (arg_int'high-1 downto 0); + end if; + else + arg_int := shift_left (arg_int, arg_int'high-to_integer(exp)); + exp := exp + in_fraction_width; + if (arg_int'high > fraction_width) then + fract := arg_int (arg_int'high-1 downto (arg_int'high-fraction_width)); + round := check_round ( + fract_in => fract(0), + sign => result(result'high), + remainder => arg_int((arg_int'high-fraction_width-1) + downto 0), + round_style => round_style); + if (round) then + fp_round (fract_in => fract, + expon_in => exp, + fract_out => fracttmp, + expon_out => exptmp); + fract := fracttmp; + exp := exptmp; + end if; + else + fract (fraction_width-1 downto fraction_width-1-(arg_int'high-1)) := + arg_int (arg_int'high-1 downto 0); + end if; + end if; + expon := UNSIGNED (resize(exp-1, exponent_width)); + expon(exponent_width-1) := not expon(exponent_width-1); + result (exponent_width-1 downto 0) := float(expon); + result (-1 downto -fraction_width) := float(fract); + end if; + return result; + end function to_float; + + -- size_res functions + -- Integer to float + function to_float ( + arg : INTEGER; + size_res : float; + constant round_style : round_type := float_round_style) -- rounding option + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style); + return result; + end if; + end function to_float; + + -- real to float + function to_float ( + arg : REAL; + size_res : float; + constant round_style : round_type := float_round_style; -- rounding option + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style, + denormalize => denormalize); + return result; + end if; + end function to_float; + + -- unsigned to float + function to_float ( + arg : UNSIGNED; + size_res : float; + constant round_style : round_type := float_round_style) -- rounding option + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style); + return result; + end if; + end function to_float; + + -- signed to float + function to_float ( + arg : SIGNED; + size_res : float; + constant round_style : round_type := float_round_style) -- rounding + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style); + return result; + end if; + end function to_float; + + -- std_logic_vector to float + function to_float ( + arg : STD_LOGIC_VECTOR; + size_res : float) + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low); + return result; + end if; + end function to_float; + + -- std_ulogic_vector to float + function to_float ( + arg : STD_ULOGIC_VECTOR; + size_res : float) + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => to_stdlogicvector(arg), + exponent_width => size_res'high, + fraction_width => -size_res'low); + return result; + end if; + end function to_float; + + -- unsigned fixed point to float + function to_float ( + arg : ufixed; -- unsigned fixed point input + size_res : float; + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- use ieee extentions + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style, + denormalize => denormalize); + return result; + end if; + end function to_float; + + -- signed fixed point to float + function to_float ( + arg : sfixed; + size_res : float; + constant round_style : round_type := float_round_style; -- rounding + constant denormalize : BOOLEAN := float_denormalize) -- rounding option + return float is + variable result : float (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_float (arg => arg, + exponent_width => size_res'high, + fraction_width => -size_res'low, + round_style => round_style, + denormalize => denormalize); + return result; + end if; + end function to_float; + + -- fp_to_integer - Floating point to integer + -- Note, to do an "int" function, call this routine with the + -- round_style set to "round_zero". + -- Synthesizable + function to_integer ( + arg : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return INTEGER is + variable validfp : valid_fpstate; -- Valid FP state + variable frac : UNSIGNED (30 downto 0); -- Fraction + variable result : INTEGER; + variable sign : STD_ULOGIC; -- true if negative + begin + validfp := class (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan | pos_zero | neg_zero | pos_denormal | neg_denormal => + result := 0; -- return 0 + when pos_inf => + result := INTEGER'high; + when neg_inf => + result := INTEGER'low; + when others => + float_to_unsigned ( + arg => arg, + frac => frac, + sign => sign, + denormalize => false, + bias => 0, + round_style => round_style); + -- Add the sign bit back in. + if sign = '1' then + -- Because the most negative signed number is 1 less than the most + -- positive signed number, we need this code. + if and_reducex(frac) = '1' then -- return most negative number + result := INTEGER'low; + else + result := -to_integer(frac); + end if; + else + result := to_integer(frac); + end if; + end case classcase; + return result; + end function to_integer; + + -- fp_to_unsigned - floating point to unsigned number + -- Synthesizable + function to_unsigned ( + arg : float; -- floating point input + constant size : NATURAL; -- length of output + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return UNSIGNED is + variable validfp : valid_fpstate; -- Valid FP state + variable frac : UNSIGNED (size-1 downto 0); -- Fraction + variable sign : STD_ULOGIC; -- not used + begin + validfp := class (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan => + frac := (others => 'X'); + when pos_zero | neg_inf | neg_zero | neg_normal | pos_denormal | neg_denormal => + frac := (others => '0'); -- return 0 + when pos_inf => + frac := (others => '1'); + when others => + float_to_unsigned ( + arg => arg, + frac => frac, + sign => sign, + denormalize => false, + bias => 0, + round_style => round_style); + end case classcase; + return (frac); + end function to_unsigned; + + -- fp_to_signed - floating point to signed number + -- Synthesizable + function to_signed ( + arg : float; -- floating point input + constant size : NATURAL; -- length of output + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return SIGNED is + variable sign : STD_ULOGIC; -- true if negative + variable validfp : valid_fpstate; -- Valid FP state + variable frac : UNSIGNED (size-1 downto 0); -- Fraction + variable result : SIGNED (size-1 downto 0); + begin + validfp := class (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan => + result := (others => 'X'); + when pos_zero | neg_zero | pos_denormal | neg_denormal => + result := (others => '0'); -- return 0 + when pos_inf => + result := (others => '1'); + result (result'high) := '0'; + when neg_inf => + result := (others => '0'); + result (result'high) := '1'; + when others => + float_to_unsigned ( + arg => arg, + sign => sign, + frac => frac, + denormalize => false, + bias => 0, + round_style => round_style); + result (size-1) := '0'; + result (size-2 downto 0) := SIGNED(frac (size-2 downto 0)); + if sign = '1' then + -- Because the most negative signed number is 1 less than the most + -- positive signed number, we need this code. + if frac(frac'high) = '1' then -- return most negative number + result := (others => '0'); + result (result'high) := '1'; + else + result := -result; + end if; + else + if frac(frac'high) = '1' then -- return most positive number + result := (others => '1'); + result (result'high) := '0'; + end if; + end if; + end case classcase; + return result; + end function to_signed; + + -- purpose: Converts a float to ufixed + function to_ufixed ( + arg : float; -- fp input + constant left_index : INTEGER; -- integer part + constant right_index : INTEGER; -- fraction part + constant round_style : BOOLEAN := fixed_round_style; -- rounding + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return ufixed is + constant fraction_width : INTEGER := -minx(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : INTEGER := arg'high; -- length of FP output exponent + constant size : INTEGER := left_index - right_index + 4; -- unsigned size + variable expon_base : INTEGER; -- exponent offset + variable validfp : valid_fpstate; -- Valid FP state + variable exp : INTEGER; -- Exponent + variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent + -- Base to divide fraction by + variable frac : UNSIGNED (size-1 downto 0) := (others => '0'); -- Fraction + variable frac_shift : UNSIGNED (size-1 downto 0); -- Fraction shifted + variable shift : INTEGER; + variable result_big : ufixed (left_index downto right_index-3); + variable result : ufixed (left_index downto right_index); -- result + begin -- function to_ufixed + validfp := class (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan => + frac := (others => 'X'); + when pos_zero | neg_inf | neg_zero | neg_normal | neg_denormal => + frac := (others => '0'); -- return 0 + when pos_inf => + frac := (others => '1'); -- always saturate + when others => + expon_base := 2**(exponent_width-1) -1; -- exponent offset + -- Figure out the fraction + if (validfp = pos_denormal) and denormalize then + exp := -expon_base +1; + frac (frac'high) := '0'; -- Add the "1.0". + else + -- exponent /= '0', normal floating point + expon := UNSIGNED(arg (exponent_width-1 downto 0)); + expon(exponent_width-1) := not expon(exponent_width-1); + exp := to_integer (SIGNED(expon)) +1; + frac (frac'high) := '1'; -- Add the "1.0". + end if; + shift := (frac'high - 3 + right_index) - exp; + if fraction_width > frac'high then -- Can only use size-2 bits + frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto + -frac'high))); + else -- can use all bits + frac (frac'high-1 downto frac'high-fraction_width) := + UNSIGNED (to_slv (arg(-1 downto -fraction_width))); + end if; + frac_shift := frac srl shift; + if shift < 0 then -- Overflow + frac := (others => '1'); + else + frac := frac_shift; + end if; + end case classcase; + result_big := to_ufixed (arg => STD_LOGIC_VECTOR(frac), + left_index => left_index, + right_index => (right_index-3)); + result := resize (arg => result_big, + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + return result; + end function to_ufixed; + + -- purpose: Converts a float to sfixed + function to_sfixed ( + arg : float; -- fp input + constant left_index : INTEGER; -- integer part + constant right_index : INTEGER; -- fraction part + constant round_style : BOOLEAN := fixed_round_style; -- rounding + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return sfixed is + constant fraction_width : INTEGER := -minx(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : INTEGER := arg'high; -- length of FP output exponent + constant size : INTEGER := left_index - right_index + 4; -- unsigned size + variable expon_base : INTEGER; -- exponent offset + variable validfp : valid_fpstate; -- Valid FP state + variable exp : INTEGER; -- Exponent + variable sign : BOOLEAN; -- true if negative + variable expon : UNSIGNED (exponent_width-1 downto 0); -- Vectorized exponent + -- Base to divide fraction by + variable frac : UNSIGNED (size-2 downto 0) := (others => '0'); -- Fraction + variable frac_shift : UNSIGNED (size-2 downto 0); -- Fraction shifted + variable shift : INTEGER; + variable rsigned : SIGNED (size-1 downto 0); -- signed version of result + variable result_big : sfixed (left_index downto right_index-3); + variable result : sfixed (left_index downto right_index) := (others => '0'); -- result + begin -- function to_ufixed + validfp := class (arg, check_error); + classcase : case validfp is + when isx | nan | quiet_nan => + result := (others => 'X'); + when pos_zero | neg_zero => + result := (others => '0'); -- return 0 + when neg_inf => + result (left_index) := '1'; -- return smallest negative number + when pos_inf => + result := (others => '1'); -- return largest number + result (left_index) := '0'; + when others => + expon_base := 2**(exponent_width-1) -1; -- exponent offset + if arg(exponent_width) = '0' then + sign := false; + else + sign := true; + end if; + -- Figure out the fraction + if (validfp = pos_denormal or validfp = neg_denormal) + and denormalize then + exp := -expon_base +1; + frac (frac'high) := '0'; -- Add the "1.0". + else + -- exponent /= '0', normal floating point + expon := UNSIGNED(arg (exponent_width-1 downto 0)); + expon(exponent_width-1) := not expon(exponent_width-1); + exp := to_integer (SIGNED(expon)) +1; + frac (frac'high) := '1'; -- Add the "1.0". + end if; + shift := (frac'high - 3 + right_index) - exp; + if fraction_width > frac'high then -- Can only use size-2 bits + frac (frac'high-1 downto 0) := UNSIGNED (to_slv (arg(-1 downto + -frac'high))); + else -- can use all bits + frac (frac'high-1 downto frac'high-fraction_width) := + UNSIGNED (to_slv (arg(-1 downto -fraction_width))); + end if; + frac_shift := frac srl shift; + if shift < 0 then -- Overflow + frac := (others => '1'); + else + frac := frac_shift; + end if; + if not sign then + rsigned := SIGNED("0" & frac); + else + rsigned := -(SIGNED("0" & frac)); + end if; + result_big := to_sfixed (arg => STD_LOGIC_VECTOR(rsigned), + left_index => left_index, + right_index => (right_index-3)); + result := resize (arg => result_big, + left_index => left_index, + right_index => right_index, + round_style => round_style, + overflow_style => overflow_style); + end case classcase; + return result; + end function to_sfixed; + + -- size_res versions + -- float to unsigned + function to_unsigned ( + arg : float; -- floating point input + size_res : UNSIGNED; + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return UNSIGNED is + variable result : UNSIGNED (size_res'range); + begin + if (SIZE_RES'length = 0) then + return result; + else + result := to_unsigned (arg => arg, + size => size_res'length, + check_error => check_error, + round_style => round_style); + return result; + end if; + end function to_unsigned; + + -- float to signed + function to_signed ( + arg : float; -- floating point input + size_res : SIGNED; + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant round_style : round_type := float_round_style) -- rounding option + return SIGNED is + variable result : SIGNED (size_res'range); + begin + if (SIZE_RES'length = 0) then + return result; + else + result := to_signed (arg => arg, + size => size_res'length, + check_error => check_error, + round_style => round_style); + return result; + end if; + end function to_signed; + + -- purpose: Converts a float to unsigned fixed point + function to_ufixed ( + arg : float; -- fp input + size_res : ufixed; + constant round_style : BOOLEAN := fixed_round_style; -- rounding + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return ufixed is + variable result : ufixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_ufixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style, + check_error => check_error, + denormalize => denormalize); + return result; + end if; + end function to_ufixed; + + -- float to signed fixed point + function to_sfixed ( + arg : float; -- fp input + size_res : sfixed; + constant round_style : BOOLEAN := fixed_round_style; -- rounding + constant overflow_style : BOOLEAN := fixed_overflow_style; -- saturate + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return sfixed is + variable result : sfixed (size_res'left downto size_res'right); + begin + if (result'length < 1) then + return result; + else + result := to_sfixed (arg => arg, + left_index => size_res'high, + right_index => size_res'low, + round_style => round_style, + overflow_style => overflow_style, + check_error => check_error, + denormalize => denormalize); + return result; + end if; + end function to_sfixed; + + -- Floating point to Real number conversion + -- Not Synthesizable + function to_real ( + arg : float; -- floating point input + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return REAL is + constant fraction_width : INTEGER := -minx(arg'low, arg'low); -- length of FP output fraction + constant exponent_width : INTEGER := arg'high; -- length of FP output exponent + variable sign : REAL; -- Sign, + or - 1 + variable exp : INTEGER; -- Exponent + variable expon_base : INTEGER; -- exponent offset + variable frac : REAL := 0.0; -- Fraction + variable validfp : valid_fpstate; -- Valid FP state + variable expon : UNSIGNED (exponent_width - 1 downto 0) + := (others => '1'); -- Vectorized exponent + begin + validfp := class (arg, check_error); + classcase : case validfp is + when isx | pos_zero | neg_zero | nan | quiet_nan => + return 0.0; + when neg_inf => + return REAL'low; -- Negative infinity. + when pos_inf => + return REAL'high; -- Positive infinity + when others => + expon_base := 2**(exponent_width-1) -1; + if to_X01(arg(exponent_width)) = '0' then + sign := 1.0; + else + sign := -1.0; + end if; + -- Figure out the fraction + for i in 0 to fraction_width-1 loop + if to_X01(arg (-1 - i)) = '1' then + frac := frac + (2.0 **(-1 - i)); + end if; + end loop; -- i + if validfp = pos_normal or validfp = neg_normal or not denormalize then + -- exponent /= '0', normal floating point + expon := UNSIGNED(arg (exponent_width-1 downto 0)); + expon(exponent_width-1) := not expon(exponent_width-1); + exp := to_integer (SIGNED(expon)) +1; + sign := sign * (2.0 ** exp) * (1.0 + frac); + else -- exponent = '0', IEEE extended floating point + exp := 1 - expon_base; + sign := sign * (2.0 ** exp) * frac; + end if; + return sign; + end case classcase; + end function to_real; + + -- purpose: Removes meta-logical values from FP string + function to_01 ( + arg : float; -- floating point input + XMAP : STD_LOGIC := '0') + return float is + variable BAD_ELEMENT : BOOLEAN := false; + variable RESULT : float (arg'range); + begin -- function to_01 + if (arg'length < 1) then + assert NO_WARNING + report "FLOAT_GENERIC_PKG.TO_01: null detected, returning NAFP" + severity warning; + return NAFP; + end if; + for I in RESULT'range loop + case arg(I) is + when '0' | 'L' => RESULT(I) := '0'; + when '1' | 'H' => RESULT(I) := '1'; + when others => BAD_ELEMENT := true; + end case; + end loop; + if BAD_ELEMENT then + RESULT := (others => XMAP); + end if; + return RESULT; + end function to_01; + + function Is_X + (arg : float) + return BOOLEAN is + begin + return Is_X (to_slv(arg)); + end function Is_X; + + function to_X01 (arg : float) return float is + begin + if (arg'length < 1) then + assert NO_WARNING + report "FLOAT_GENERIC_PKG.TO_X01: null detected, returning NAFP" + severity warning; + return NAFP; + else + return to_float (to_X01(to_slv(arg)), arg'high, -arg'low); + end if; + end function to_X01; + + function to_X01Z (arg : float) return float is + begin + if (arg'length < 1) then + assert NO_WARNING + report "FLOAT_GENERIC_PKG.TO_X01Z: null detected, returning NAFP" + severity warning; + return NAFP; + else + return to_float (to_X01Z(to_slv(arg)), arg'high, -arg'low); + end if; + end function to_X01Z; + + function to_UX01 (arg : float) return float is + begin + if (arg'length < 1) then + assert NO_WARNING + report "FLOAT_GENERIC_PKG.TO_UX01: null detected, returning NAFP" + severity warning; + return NAFP; + else + return to_float (to_UX01(to_slv(arg)), arg'high, -arg'low); + end if; + end function to_UX01; + + -- These allows the base math functions to use the default values + -- of their parameters. Thus they do full IEEE floating point. + function "+" (l, r : float) return float is + begin + return add (l, r); + end function "+"; + function "-" (l, r : float) return float is + begin + return subtract (l, r); + end function "-"; + function "*" (l, r : float) return float is + begin + return multiply (l, r); + end function "*"; + function "/" (l, r : float) return float is + begin + return divide (l, r); + end function "/"; + function "rem" (l, r : float) return float is + begin + return remainder (l, r); + end function "rem"; + function "mod" (l, r : float) return float is + begin + return modulo (l, r); + end function "mod"; + -- overloaded versions + function "+" (l : float; r : REAL) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return add (l, r_float); + end function "+"; + + function "+" (l : REAL; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return add (l_float, r); + end function "+"; + + function "+" (l : float; r : INTEGER) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return add (l, r_float); + end function "+"; + + function "+" (l : INTEGER; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return add (l_float, r); + end function "+"; + + function "-" (l : float; r : REAL) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return subtract (l, r_float); + end function "-"; + + function "-" (l : REAL; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return subtract (l_float, r); + end function "-"; + + function "-" (l : float; r : INTEGER) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return subtract (l, r_float); + end function "-"; + + function "-" (l : INTEGER; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return subtract (l_float, r); + end function "-"; + + function "*" (l : float; r : REAL) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return multiply (l, r_float); + end function "*"; + + function "*" (l : REAL; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return multiply (l_float, r); + end function "*"; + + function "*" (l : float; r : INTEGER) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return multiply (l, r_float); + end function "*"; + + function "*" (l : INTEGER; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return multiply (l_float, r); + end function "*"; + + function "/" (l : float; r : REAL) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return divide (l, r_float); + end function "/"; + + function "/" (l : REAL; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return divide (l_float, r); + end function "/"; + + function "/" (l : float; r : INTEGER) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return divide (l, r_float); + end function "/"; + + function "/" (l : INTEGER; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return divide (l_float, r); + end function "/"; + + function "rem" (l : float; r : REAL) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return remainder (l, r_float); + end function "rem"; + + function "rem" (l : REAL; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return remainder (l_float, r); + end function "rem"; + + function "rem" (l : float; r : INTEGER) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return remainder (l, r_float); + end function "rem"; + + function "rem" (l : INTEGER; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return remainder (l_float, r); + end function "rem"; + + function "mod" (l : float; r : REAL) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return modulo (l, r_float); + end function "mod"; + + function "mod" (l : REAL; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return modulo (l_float, r); + end function "mod"; + + function "mod" (l : float; r : INTEGER) return float is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return modulo (l, r_float); + end function "mod"; + + function "mod" (l : INTEGER; r : float) return float is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return modulo (l_float, r); + end function "mod"; + + function "=" (l : float; r : REAL) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return eq (l, r_float); + end function "="; + + function "/=" (l : float; r : REAL) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return ne (l, r_float); + end function "/="; + + function ">=" (l : float; r : REAL) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return ge (l, r_float); + end function ">="; + + function "<=" (l : float; r : REAL) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return le (l, r_float); + end function "<="; + + function ">" (l : float; r : REAL) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return gt (l, r_float); + end function ">"; + + function "<" (l : float; r : REAL) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return lt (l, r_float); + end function "<"; + + function "=" (l : REAL; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return eq (l_float, r); + end function "="; + + function "/=" (l : REAL; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return ne (l_float, r); + end function "/="; + + function ">=" (l : REAL; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return ge (l_float, r); + end function ">="; + + function "<=" (l : REAL; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return le (l_float, r); + end function "<="; + + function ">" (l : REAL; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return gt (l_float, r); + end function ">"; + + function "<" (l : REAL; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return lt (l_float, r); + end function "<"; + + function "=" (l : float; r : INTEGER) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return eq (l, r_float); + end function "="; + + function "/=" (l : float; r : INTEGER) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return ne (l, r_float); + end function "/="; + + function ">=" (l : float; r : INTEGER) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return ge (l, r_float); + end function ">="; + + function "<=" (l : float; r : INTEGER) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return le (l, r_float); + end function "<="; + + function ">" (l : float; r : INTEGER) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return gt (l, r_float); + end function ">"; + + function "<" (l : float; r : INTEGER) return BOOLEAN is + variable r_float : float (l'range); + begin + r_float := to_float (r, l); -- use size_res function + return lt (l, r_float); + end function "<"; + + function "=" (l : INTEGER; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return eq (l_float, r); + end function "="; + + function "/=" (l : INTEGER; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return ne (l_float, r); + end function "/="; + + function ">=" (l : INTEGER; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return ge (l_float, r); + end function ">="; + + function "<=" (l : INTEGER; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return le (l_float, r); + end function "<="; + + function ">" (l : INTEGER; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return gt (l_float, r); + end function ">"; + + function "<" (l : INTEGER; r : float) return BOOLEAN is + variable l_float : float (r'range); + begin + l_float := to_float(l, r); + return lt (l_float, r); + end function "<"; + + ---------------------------------------------------------------------------- + -- logical functions + ---------------------------------------------------------------------------- + function "not" (L : float) return float is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + variable resfp : float (L'range); -- back to float + begin + RESULT := not to_slv(L); + resfp := float (RESULT); + return resfp; + end function "not"; + + function "and" (L, R : float) return float is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + variable resfp : float (L'range); -- back to float + begin + RESULT := to_slv(L) and to_slv(R); + resfp := float (RESULT); + return resfp; + end function "and"; + + function "or" (L, R : float) return float is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + variable resfp : float (L'range); -- back to float + begin + RESULT := to_slv(L) or to_slv(R); + resfp := float (RESULT); + return resfp; + end function "or"; + + function "nand" (L, R : float) return float is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + variable resfp : float (L'range); -- back to float + begin + RESULT := to_slv(L) nand to_slv(R); + resfp := float (RESULT); + return resfp; + end function "nand"; + + function "nor" (L, R : float) return float is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + variable resfp : float (L'range); -- back to float + begin + RESULT := to_slv(L) nor to_slv(R); + resfp := float (RESULT); + return resfp; + end function "nor"; + + function "xor" (L, R : float) return float is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + variable resfp : float (L'range); -- back to float + begin + RESULT := to_slv(L) xor to_slv(R); + resfp := float (RESULT); + return resfp; + end function "xor"; + + function "xnor" (L, R : float) return float is + variable RESULT : STD_LOGIC_VECTOR(L'length-1 downto 0); -- force downto + variable resfp : float (L'range); -- back to float + begin + RESULT := to_slv(L) xnor to_slv(R); + resfp := float (RESULT); + return resfp; + end function "xnor"; + + -- Vector and std_ulogic functions, same as functions in numeric_std + function "and" (L : STD_ULOGIC; R : float) return float is + variable result : float (R'range); + begin + for i in result'range loop + result(i) := L and R(i); + end loop; + return result; + end function "and"; + + function "and" (L : float; R : STD_ULOGIC) return float is + variable result : float (L'range); + begin + for i in result'range loop + result(i) := L(i) and R; + end loop; + return result; + end function "and"; + + function "or" (L : STD_ULOGIC; R : float) return float is + variable result : float (R'range); + begin + for i in result'range loop + result(i) := L or R(i); + end loop; + return result; + end function "or"; + + function "or" (L : float; R : STD_ULOGIC) return float is + variable result : float (L'range); + begin + for i in result'range loop + result(i) := L(i) or R; + end loop; + return result; + end function "or"; + + function "nand" (L : STD_ULOGIC; R : float) return float is + variable result : float (R'range); + begin + for i in result'range loop + result(i) := L nand R(i); + end loop; + return result; + end function "nand"; + + function "nand" (L : float; R : STD_ULOGIC) return float is + variable result : float (L'range); + begin + for i in result'range loop + result(i) := L(i) nand R; + end loop; + return result; + end function "nand"; + + function "nor" (L : STD_ULOGIC; R : float) return float is + variable result : float (R'range); + begin + for i in result'range loop + result(i) := L nor R(i); + end loop; + return result; + end function "nor"; + + function "nor" (L : float; R : STD_ULOGIC) return float is + variable result : float (L'range); + begin + for i in result'range loop + result(i) := L(i) nor R; + end loop; + return result; + end function "nor"; + + function "xor" (L : STD_ULOGIC; R : float) return float is + variable result : float (R'range); + begin + for i in result'range loop + result(i) := L xor R(i); + end loop; + return result; + end function "xor"; + + function "xor" (L : float; R : STD_ULOGIC) return float is + variable result : float (L'range); + begin + for i in result'range loop + result(i) := L(i) xor R; + end loop; + return result; + end function "xor"; + + function "xnor" (L : STD_ULOGIC; R : float) return float is + variable result : float (R'range); + begin + for i in result'range loop + result(i) := L xnor R(i); + end loop; + return result; + end function "xnor"; + + function "xnor" (L : float; R : STD_ULOGIC) return float is + variable result : float (L'range); + begin + for i in result'range loop + result(i) := L(i) xnor R; + end loop; + return result; + end function "xnor"; + + -- Reduction operators, same as numeric_std functions + -- %%% remove 6 functions (old syntax) + function and_reduce(arg : float) return STD_ULOGIC is + begin + return and_reducex (to_slv(arg)); + end function and_reduce; + + function nand_reduce(arg : float) return STD_ULOGIC is + begin + return not and_reducex (to_slv(arg)); + end function nand_reduce; + + function or_reduce(arg : float) return STD_ULOGIC is + begin + return or_reducex (to_slv(arg)); + end function or_reduce; + + function nor_reduce(arg : float) return STD_ULOGIC is + begin + return not or_reducex (to_slv(arg)); + end function nor_reduce; + + function xor_reduce(arg : float) return STD_ULOGIC is + begin + return xor_reducex (to_slv(arg)); + end function xor_reduce; + + function xnor_reduce(arg : float) return STD_ULOGIC is + begin + return not xor_reducex (to_slv(arg)); + end function xnor_reduce; + + -- %%% Uncomment the following 6 functions (new syntax) + -- function "and" ( arg : float ) RETURN std_ulogic is + -- begin + -- return and to_slv(arg); + -- end function "and"; + -- function "nand" ( arg : float ) RETURN std_ulogic is + -- begin + -- return nand to_slv(arg); + -- end function "nand";; + -- function "or" ( arg : float ) RETURN std_ulogic is + -- begin + -- return or to_slv(arg); + -- end function "or"; + -- function "nor" ( arg : float ) RETURN std_ulogic is + -- begin + -- return nor to_slv(arg); + -- end function "nor"; + -- function "xor" ( arg : float ) RETURN std_ulogic is + -- begin + -- return xor to_slv(arg); + -- end function "xor"; + -- function "xnor" ( arg : float ) RETURN std_ulogic is + -- begin + -- return xnor to_slv(arg); + -- end function "xnor"; + ----------------------------------------------------------------------------- + -- Recommended Functions from the IEEE 754 Appendix + ----------------------------------------------------------------------------- + -- returns x with the sign of y. + function Copysign ( + x, y : float) -- floating point input + return float is + begin + return y(y'high) & x (x'high-1 downto x'low); + end function Copysign; + + -- Returns y * 2**n for integral values of N without computing 2**n + function Scalb ( + y : float; -- floating point input + N : INTEGER; -- exponent to add + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + constant fraction_width : NATURAL := -minx(y'low, y'low); -- length of FP output fraction + constant exponent_width : NATURAL := y'high; -- length of FP output exponent + variable arg, result : float (exponent_width downto -fraction_width); -- internal argument + variable expon : SIGNED (exponent_width-1 downto 0); -- Vectorized exp + variable exp : SIGNED (exponent_width downto 0); + variable ufract : UNSIGNED (fraction_width downto 0); + constant expon_base : SIGNED (exponent_width-1 downto 0) + := gen_expon_base(exponent_width); -- exponent offset + variable fptype : valid_fpstate; + begin + -- This can be done by simply adding N to the exponent. + arg := to_01 (y, 'X'); + fptype := class(arg, check_error); + classcase : case fptype is + when isx => + result := (others => 'X'); + when nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + result := qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + when others => + break_number ( + arg => arg, + fptyp => fptype, + denormalize => denormalize, + fract => ufract, + expon => expon); + exp := resize (expon, exp'length) + N; + result := normalize ( + fract => ufract, + expon => exp, + sign => to_x01 (arg (arg'high)), + fraction_width => fraction_width, + exponent_width => exponent_width, + round_style => round_style, + denormalize => denormalize, + nguard => 0); + end case classcase; + return result; + end function Scalb; + + -- Returns y * 2**n for integral values of N without computing 2**n + function Scalb ( + y : float; -- floating point input + N : SIGNED; -- exponent to add + constant round_style : round_type := float_round_style; -- rounding option + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) -- Use IEEE extended FP + return float is + variable n_int : INTEGER; + begin + n_int := to_integer(N); + return Scalb (y => y, + N => n_int, + round_style => round_style, + check_error => check_error, + denormalize => denormalize); + end function Scalb; + + -- returns the unbiased exponent of x + function Logb ( + x : float) -- floating point input + return INTEGER is + constant fraction_width : NATURAL := -minx (x'low, x'low); -- length of FP output fraction + constant exponent_width : NATURAL := x'high; -- length of FP output exponent + variable result : INTEGER; -- result + variable arg : float (exponent_width downto -fraction_width); -- internal argument + variable expon : SIGNED (exponent_width - 1 downto 0); + variable fract : UNSIGNED (fraction_width downto 0); + constant expon_base : INTEGER := 2**(exponent_width-1) -1; -- exponent + -- offset +1 + variable fptype : valid_fpstate; + begin + -- Just return the exponent. + arg := to_01 (x, 'X'); + fptype := class(arg); + classcase : case fptype is + when isx | nan | quiet_nan => + -- Return quiet NAN, IEEE754-1985-7.1,1 + result := 0; + when pos_denormal | neg_denormal => + fract (fraction_width) := '0'; + fract (fraction_width-1 downto 0) := + UNSIGNED (to_slv(arg(-1 downto -fraction_width))); + result := find_msb (fract, '1') -- Find the first "1" + - fraction_width; -- subtract the length we want + result := -expon_base + 1 + result; + when others => + expon := SIGNED(arg (exponent_width - 1 downto 0)); + expon(exponent_width-1) := not expon(exponent_width-1); + expon := expon + 1; + result := to_integer (expon); + end case classcase; + return result; + end function Logb; + + -- returns the unbiased exponent of x + function Logb ( + x : float) -- floating point input + return SIGNED is + constant exponent_width : NATURAL := x'high; -- length of FP output exponent + variable result : SIGNED (exponent_width - 1 downto 0); -- result + begin + -- Just return the exponent. + result := to_signed (Logb (x), exponent_width); + return result; + end function Logb; + + -- returns the next representable neighbor of x in the direction toward y + function Nextafter ( + x, y : float; -- floating point input + constant check_error : BOOLEAN := float_check_error; -- check for errors + constant denormalize : BOOLEAN := float_denormalize) + return float is + constant fraction_width : NATURAL := -minx(x'low, x'low); -- length of FP output fraction + constant exponent_width : NATURAL := x'high; -- length of FP output exponent + function "=" ( + l, r : float) -- inputs + return BOOLEAN is + begin -- function "=" + return eq (l => l, + r => r, + check_error => false); + end function "="; + function ">" ( + l, r : float) -- inputs + return BOOLEAN is + begin -- function ">" + return gt (l => l, + r => r, + check_error => false); + end function ">"; + variable fract : UNSIGNED (fraction_width-1 downto 0); + variable expon : UNSIGNED (exponent_width-1 downto 0); + variable sign : STD_ULOGIC; + variable result : float (exponent_width downto -fraction_width); + variable validfpx, validfpy : valid_fpstate; -- Valid FP state + begin -- fp_Nextafter + -- If Y > X, add one to the fraction, otherwise subtract. + validfpx := class (x, check_error); + validfpy := class (y, check_error); + if validfpx = isx or validfpy = isx then + result := (others => 'X'); + return result; + elsif (validfpx = nan or validfpy = nan) then + return nanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif (validfpx = quiet_nan or validfpy = quiet_nan) then + return qnanfp (fraction_width => fraction_width, + exponent_width => exponent_width); + elsif x = y then -- Return X + return x; + else + fract := UNSIGNED (to_slv (x (-1 downto -fraction_width))); -- Fraction + expon := UNSIGNED (x (exponent_width - 1 downto 0)); -- exponent + sign := x(exponent_width); -- sign bit + if (y > x) then + -- Increase the number given + if validfpx = neg_inf then + -- return most negative number + expon := (others => '1'); + expon (0) := '0'; + fract := (others => '1'); + elsif validfpx = pos_zero or validfpx = neg_zero then + -- return smallest denormal number + sign := '0'; + expon := (others => '0'); + fract := (others => '0'); + fract(0) := '1'; + elsif validfpx = pos_normal then + if and_reducex (fract) = '1' then -- fraction is all "1". + if and_reducex (expon (exponent_width-1 downto 1)) = '1' + and expon (0) = '0' then + -- Exponent is one away from infinity. + assert NO_WARNING + report "FLOAT_GENERIC_PKG.FP_NEXTAFTER: NextAfter overflow" + severity warning; + return pos_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + expon := expon + 1; + fract := (others => '0'); + end if; + else + fract := fract + 1; + end if; + elsif validfpx = pos_denormal then + if and_reducex (fract) = '1' then -- fraction is all "1". + -- return smallest possible normal number + expon := (others => '0'); + expon(0) := '1'; + fract := (others => '0'); + else + fract := fract + 1; + end if; + elsif validfpx = neg_normal then + if or_reducex (fract) = '0' then -- fraction is all "0". + if or_reducex (expon (exponent_width-1 downto 1)) = '0' and + expon (0) = '1' then -- Smallest exponent + -- return the largest negative denormal number + expon := (others => '0'); + fract := (others => '1'); + else + expon := expon - 1; + fract := (others => '1'); + end if; + else + fract := fract - 1; + end if; + elsif validfpx = neg_denormal then + if or_reducex (fract(fract'high downto 1)) = '0' + and fract (0) = '1' then -- Smallest possible fraction + return zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + fract := fract - 1; + end if; + end if; + else + -- Decrease the number + if validfpx = pos_inf then + -- return most positive number + expon := (others => '1'); + expon (0) := '0'; + fract := (others => '1'); + elsif validfpx = pos_zero + or class (x) = neg_zero then + -- return smallest negative denormal number + sign := '1'; + expon := (others => '0'); + fract := (others => '0'); + fract(0) := '1'; + elsif validfpx = neg_normal then + if and_reducex (fract) = '1' then -- fraction is all "1". + if and_reducex (expon (exponent_width-1 downto 1)) = '1' + and expon (0) = '0' then + -- Exponent is one away from infinity. + assert NO_WARNING + report "FLOAT_GENERIC_PKG.FP_NEXTAFTER: NextAfter overflow" + severity warning; + return neg_inffp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + expon := expon + 1; -- Fraction overflow + fract := (others => '0'); + end if; + else + fract := fract + 1; + end if; + elsif validfpx = neg_denormal then + if and_reducex (fract) = '1' then -- fraction is all "1". + -- return smallest possible normal number + expon := (others => '0'); + expon(0) := '1'; + fract := (others => '0'); + else + fract := fract + 1; + end if; + elsif validfpx = pos_normal then + if or_reducex (fract) = '0' then -- fraction is all "0". + if or_reducex (expon (exponent_width-1 downto 1)) = '0' and + expon (0) = '1' then -- Smallest exponent + -- return the largest positive denormal number + expon := (others => '0'); + fract := (others => '1'); + else + expon := expon - 1; + fract := (others => '1'); + end if; + else + fract := fract - 1; + end if; + elsif validfpx = pos_denormal then + if or_reducex (fract(fract'high downto 1)) = '0' + and fract (0) = '1' then -- Smallest possible fraction + return zerofp (fraction_width => fraction_width, + exponent_width => exponent_width); + else + fract := fract - 1; + end if; + end if; + end if; + result (-1 downto -fraction_width) := float(fract); + result (exponent_width -1 downto 0) := float(expon); + result (exponent_width) := sign; + return result; + end if; + end function Nextafter; + + -- Returns True if X is unordered with Y. + function Unordered ( + x, y : float) -- floating point input + return BOOLEAN is + variable lfptype, rfptype : valid_fpstate; + begin + lfptype := class (x); + rfptype := class (y); + if (lfptype = nan or lfptype = quiet_nan or + rfptype = nan or rfptype = quiet_nan or + lfptype = isx or rfptype = isx) then + return true; + else + return false; + end if; + end function Unordered; + + function Finite ( + x : float) + return BOOLEAN is + variable fp_state : valid_fpstate; -- fp state + begin + fp_state := Class (x); + if (fp_state = pos_inf) or (fp_state = neg_inf) then + return true; + else + return false; + end if; + end function Finite; + + function Isnan ( + x : float) + return BOOLEAN is + variable fp_state : valid_fpstate; -- fp state + begin + fp_state := Class (x); + if (fp_state = nan) or (fp_state = quiet_nan) then + return true; + else + return false; + end if; + end function Isnan; + + -- Function to return constants. + function zerofp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float is + constant result : float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + return result; + end function zerofp; + function nanfp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float is + variable result : float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width-1 downto 0) := (others => '1'); + -- Exponent all "1" + result (-1) := '1'; -- MSB of Fraction "1" + -- Note: From W. Khan "IEEE Standard 754 for Binary Floating Point" + -- The difference between a signaling NAN and a quiet NAN is that + -- the MSB of the Fraction is a "1" in a Signaling NAN, and is a + -- "0" in a quiet NAN. + return result; + end function nanfp; + function qnanfp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float is + variable result : float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width-1 downto 0) := (others => '1'); + -- Exponent all "1" + result (-fraction_width) := '1'; -- LSB of Fraction "1" + -- (Could have been any bit) + return result; + end function qnanfp; + function pos_inffp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float is + variable result : float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width-1 downto 0) := (others => '1'); -- Exponent all "1" + return result; + end function pos_inffp; + function neg_inffp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float is + variable result : float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width downto 0) := (others => '1'); -- top bits all "1" + return result; + end function neg_inffp; + function neg_zerofp ( + constant exponent_width : NATURAL := float_exponent_width; -- exponent + constant fraction_width : NATURAL := float_fraction_width) -- fraction + return float is + variable result : float (exponent_width downto -fraction_width) := + (others => '0'); -- zero + begin + result (exponent_width) := '1'; + return result; + end function neg_zerofp; + -- size_res versions + function zerofp ( + size_res : float) -- variable is only use for sizing + return float is + begin + return zerofp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function zerofp; + function nanfp ( + size_res : float) -- variable is only use for sizing + return float is + begin + return nanfp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function nanfp; + function qnanfp ( + size_res : float) -- variable is only use for sizing + return float is + begin + return qnanfp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function qnanfp; + function pos_inffp ( + size_res : float) -- variable is only use for sizing + return float is + begin + return pos_inffp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function pos_inffp; + function neg_inffp ( + size_res : float) -- variable is only use for sizing + return float is + begin + return neg_inffp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function neg_inffp; + function neg_zerofp ( + size_res : float) -- variable is only use for sizing + return float is + begin + return neg_zerofp ( + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function neg_zerofp; + +-- rtl_synthesis off + -- synthesis translate_off + -- purpose: writes float into a line (NOTE changed basetype) + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', error); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of CHARACTER; + type MVL9_indexed_by_char is array (CHARACTER) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (CHARACTER) of MVL9plus; + + constant MVL9_to_char : char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9 : MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus : MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => error); + + -- %%% Remove the following lines for inclution in VHDL-200x-ft + constant NUS : STRING(2 to 1) := (others => ' '); -- NULL array + function justify ( + value : STRING; + justified : SIDE := right; + field : width := 0) + return STRING is + constant VAL_LEN : INTEGER := value'length; + variable result : STRING (1 to field) := (others => ' '); + begin -- function justify + -- return value if field is too small + if VAL_LEN >= field then + return value; + end if; + if justified = left then + result(1 to VAL_LEN) := value; + elsif justified = right then + result(field - VAL_LEN + 1 to field) := value; + end if; + return result; + end function justify; + ------------------------------------------------------------------- + -- TO_HSTRING + ------------------------------------------------------------------- + function to_hstring ( + value : STD_LOGIC_VECTOR; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := (value'length+3)/4; + variable pad : STD_LOGIC_VECTOR(0 to (ne*4 - value'length) - 1); + variable ivalue : STD_LOGIC_VECTOR(0 to ne*4 - 1); + variable result : STRING(1 to ne); + variable quad : STD_LOGIC_VECTOR(0 to 3); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + quad := To_X01Z(ivalue(4*i to 4*i+3)); + case quad is + when x"0" => result(i+1) := '0'; + when x"1" => result(i+1) := '1'; + when x"2" => result(i+1) := '2'; + when x"3" => result(i+1) := '3'; + when x"4" => result(i+1) := '4'; + when x"5" => result(i+1) := '5'; + when x"6" => result(i+1) := '6'; + when x"7" => result(i+1) := '7'; + when x"8" => result(i+1) := '8'; + when x"9" => result(i+1) := '9'; + when x"A" => result(i+1) := 'A'; + when x"B" => result(i+1) := 'B'; + when x"C" => result(i+1) := 'C'; + when x"D" => result(i+1) := 'D'; + when x"E" => result(i+1) := 'E'; + when x"F" => result(i+1) := 'F'; + when "ZZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_hstring; + + ------------------------------------------------------------------- + -- TO_OSTRING + ------------------------------------------------------------------- + function to_ostring ( + value : STD_LOGIC_VECTOR; + justified : SIDE := right; + field : width := 0 + ) return STRING is + constant ne : INTEGER := (value'length+2)/3; + variable pad : STD_LOGIC_VECTOR(0 to (ne*3 - value'length) - 1); + variable ivalue : STD_LOGIC_VECTOR(0 to ne*3 - 1); + variable result : STRING(1 to ne); + variable tri : STD_LOGIC_VECTOR(0 to 2); + begin + if value'length < 1 then + return NUS; + else + if value (value'left) = 'Z' then + pad := (others => 'Z'); + else + pad := (others => '0'); + end if; + ivalue := pad & value; + for i in 0 to ne-1 loop + tri := To_X01Z(ivalue(3*i to 3*i+2)); + case tri is + when o"0" => result(i+1) := '0'; + when o"1" => result(i+1) := '1'; + when o"2" => result(i+1) := '2'; + when o"3" => result(i+1) := '3'; + when o"4" => result(i+1) := '4'; + when o"5" => result(i+1) := '5'; + when o"6" => result(i+1) := '6'; + when o"7" => result(i+1) := '7'; + when "ZZZ" => result(i+1) := 'Z'; + when others => result(i+1) := 'X'; + end case; + end loop; + return justify(result, justified, field); + end if; + end function to_ostring; + -- %%% end remove lines + + procedure write ( + L : inout LINE; -- input line + VALUE : in float; -- floating point input + JUSTIFIED : in SIDE := right; + FIELD : in WIDTH := 0) is + variable s : STRING(1 to value'high - value'low +3); + variable sindx : INTEGER; + begin -- function write + s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high))); + s(2) := ':'; + sindx := 3; + for i in VALUE'high-1 downto 0 loop + s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); + sindx := sindx + 1; + end loop; + s(sindx) := ':'; + sindx := sindx + 1; + for i in -1 downto VALUE'low loop + s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); + sindx := sindx + 1; + end loop; + write(L, s, JUSTIFIED, FIELD); + end procedure write; + + procedure READ(L : inout LINE; VALUE : out float) is + -- Possible data: 0:0000:0000000 + -- 000000000000 + variable c : CHARACTER; + variable readOk : BOOLEAN; + variable i : INTEGER; -- index variable + begin -- READ + loop -- skip white space + read(l, c, readOk); + exit when ((readOk = false) or ((c /= ' ') and (c /= CR) and (c /= HT))); + end loop; + for i in value'high downto value'low loop + value(i) := 'X'; + end loop; + i := value'high; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + report "FLOAT_GENERIC_PKG.READ(float): " + & "Error end of file encountered."; + return; + elsif c = ' ' or c = CR or c = HT then -- reading done. + if (i /= value'low) then + report "FLOAT_GENERIC_PKG.READ(float): " + & "Warning: Value truncated."; + return; + end if; + elsif c = ':' or c = '.' then -- seperator, ignore + if not (i = -1 or i = value'high-1) then + report "FLOAT_GENERIC_PKG.READ(float): " + & "Warning: Seperator point does not match number format: '" + & c & "' ecountered at location " & INTEGER'image(i) & "."; + end if; + elsif (char_to_MVL9plus(c) = error) then + report "FLOAT_GENERIC_PKG.READ(float): " + & "Error: Character '" & c & "' read, expected STD_ULOGIC literal."; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + procedure READ(L : inout LINE; VALUE : out float; GOOD : out BOOLEAN) is + -- Possible data: 0:0000:0000000 + -- 000000000000 + variable c : CHARACTER; + variable i : INTEGER; -- index variable + variable readOk : BOOLEAN; + begin -- READ + loop -- skip white space + read(l, c, readOk); + exit when ((readOk = false) or ((c /= ' ') and (c /= CR) and (c /= HT))); + end loop; + for i in value'high downto value'low loop + value(i) := 'X'; + end loop; + i := value'high; + good := true; + readloop : loop + if readOk = false then -- Bail out if there was a bad read + good := false; + return; + elsif c = ' ' or c = CR or c = HT then -- reading done + good := false; + return; + elsif c = ':' or c = '.' then -- seperator, ignore + good := (i = -1 or i = value'high-1); + elsif (char_to_MVL9plus(c) = error) then + good := false; + return; + else + value (i) := char_to_MVL9(c); + i := i - 1; + if i < value'low then + return; + end if; + end if; + read(l, c, readOk); + end loop readloop; + end procedure READ; + + procedure owrite ( + L : inout LINE; -- access type (pointer) + VALUE : in float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0) is -- width of field + begin + write (L => L, + VALUE => to_ostring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure owrite; + + procedure OREAD(L : inout LINE; VALUE : out float) is + constant ne : INTEGER := ((value'length+2)/3) * 3; -- pad + variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv + variable dummy : CHARACTER; -- to read the "." + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + OREAD (L => L, + VALUE => nybble, + good => igood); + assert (igood) + report "FLOAT_GENERIC_PKG.OREAD: Failed to skip white space " & L.all + severity error; + i := ne-1 - 3; -- Top - 3 + slv (ne-1 downto i+1) := nybble; + while (i /= -1) and igood and L.all'length /= 0 loop + if (L.all(1) = '.') or (L.all(1) = ':') then + read (L, dummy); + else + OREAD (L => L, + VALUE => nybble, + good => igood); + assert (igood) + report "FLOAT_GENERIC_PKG.OREAD: Failed to read the string " & L.all + severity error; + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end loop; + assert igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(ne-1 downto VALUE'high-VALUE'low+1)) = '0') + report "FLOAT_GENERIC_PKG.OREAD: Vector truncated." + severity error; + value := to_float (slv(VALUE'high-VALUE'low downto 0), + value'high, -value'low); + end procedure OREAD; + + procedure OREAD(L : inout LINE; VALUE : out float; GOOD : out BOOLEAN) is + constant ne : INTEGER := ((value'length+2)/3) * 3; -- pad + variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv + variable dummy : CHARACTER; -- to read the "." + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (2 downto 0); -- 3 bits + variable i : INTEGER; + begin + OREAD (L => L, + VALUE => nybble, + good => igood); + i := ne-1 - 3; -- Top - 3 + slv (ne-1 downto i+1) := nybble; + while (i /= -1) and igood and L.all'length /= 0 loop + if (L.all(1) = '.') or (L.all(1) = ':') then + read (L, dummy, igood); + else + OREAD (L => L, + VALUE => nybble, + good => igood); + slv (i downto i-2) := nybble; + i := i - 3; + end if; + end loop; + good := igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(ne-1 downto VALUE'high-VALUE'low+1)) = '0'); + value := to_float (slv(VALUE'high-VALUE'low downto 0), + value'high, -value'low); + end procedure OREAD; + + procedure hwrite ( + L : inout LINE; -- access type (pointer) + VALUE : in float; -- value to write + JUSTIFIED : in SIDE := right; -- which side to justify text + FIELD : in WIDTH := 0) is -- width of field + begin + write (L => L, + VALUE => to_hstring(VALUE), + JUSTIFIED => JUSTIFIED, + FIELD => FIELD); + end procedure hwrite; + + procedure HREAD(L : inout LINE; VALUE : out float) is + constant ne : INTEGER := ((value'length+3)/4) * 4; -- pad + variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv + variable dummy : CHARACTER; -- to read the "." + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + HREAD (L => L, + VALUE => nybble, + good => igood); + assert (igood) + report "FLOAT_GENERIC_PKG.HREAD: Failed to skip white space " & L.all + severity error; + i := ne - 1 - 4; -- Top - 4 + slv (ne -1 downto i+1) := nybble; + while (i /= -1) and igood and L.all'length /= 0 loop + if (L.all(1) = '.') or (L.all(1) = ':') then + read (L, dummy); + else + HREAD (L => L, + VALUE => nybble, + good => igood); + assert (igood) + report "FLOAT_GENERIC_PKG.HREAD: Failed to read the string " & L.all + severity error; + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end loop; + assert igood and -- We did not get another error + (i = -1) and -- We read everything + (or_reducex(slv(ne-1 downto VALUE'high-VALUE'low+1)) = '0') + report "FLOAT_GENERIC_PKG.HREAD: Vector truncated." + severity error; + value := to_float (slv(VALUE'high-VALUE'low downto 0), + value'high, -value'low); + end procedure HREAD; + + procedure HREAD(L : inout LINE; VALUE : out float; GOOD : out BOOLEAN) is + constant ne : INTEGER := ((value'length+3)/4) * 4; -- pad + variable slv : STD_LOGIC_VECTOR (ne-1 downto 0); -- slv + variable dummy : CHARACTER; -- to read the "." + variable igood : BOOLEAN; + variable nybble : STD_LOGIC_VECTOR (3 downto 0); -- 4 bits + variable i : INTEGER; + begin + HREAD (L => L, + VALUE => nybble, + good => igood); + i := ne - 1 - 4; -- Top - 4 + slv (ne-1 downto i+1) := nybble; + while (i /= -1) and igood and L.all'length /= 0 loop + if (L.all(1) = '.') or (L.all(1) = ':') then + read (L, dummy, igood); + else + HREAD (L => L, + VALUE => nybble, + good => igood); + slv (i downto i-3) := nybble; + i := i - 4; + end if; + end loop; + good := igood and -- We did not get another error + (i = -1) and -- We read everything, and high bits 0 + (or_reducex(slv(ne-1 downto VALUE'high-VALUE'low+1)) = '0'); + value := to_float (slv(VALUE'high-VALUE'low downto 0), + value'high, -value'low); + end procedure HREAD; + + function to_string ( + value : float; + justified : SIDE := right; + field : width := 0 + ) return STRING is + variable s : STRING(1 to value'high - value'low +3); + variable sindx : INTEGER; + begin -- function write + s(1) := MVL9_to_char(STD_ULOGIC(VALUE(VALUE'high))); + s(2) := ':'; + sindx := 3; + for i in VALUE'high-1 downto 0 loop + s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); + sindx := sindx + 1; + end loop; + s(sindx) := ':'; + sindx := sindx + 1; + for i in -1 downto VALUE'low loop + s(sindx) := MVL9_to_char(STD_ULOGIC(VALUE(i))); + sindx := sindx + 1; + end loop; + return justify (s, JUSTIFIED, FIELD); + end function to_string; + + function to_hstring ( + value : float; + justified : SIDE := right; + field : width := 0 + ) return STRING is + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + floop : for i in slv'range loop + slv(i) := to_X01Z (value(i + value'low)); + end loop floop; + return to_hstring (slv, justified, field); + end function to_hstring; + + function to_ostring ( + value : float; + justified : SIDE := right; + field : width := 0 + ) return STRING is + variable slv : STD_LOGIC_VECTOR (value'length-1 downto 0); + begin + floop : for i in slv'range loop + slv(i) := to_X01Z (value(i + value'low)); + end loop floop; + return to_ostring (slv, justified, field); + end function to_ostring; + + function from_string ( + bstring : STRING; -- binary string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return float is + variable result : float (exponent_width downto -fraction_width); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(bstring); + read (L, result, good); + deallocate (L); + assert (good) + report "FLOAT_GENERIC_PKG.from_string: Bad string " & bstring + severity error; + return result; + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return float is + variable result : float (exponent_width downto -fraction_width); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(ostring); + oread (L, result, good); + deallocate (L); + assert (good) + report "FLOAT_GENERIC_PKG.from_ostring: Bad string " & ostring + severity error; + return result; + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + constant exponent_width : NATURAL := float_exponent_width; + constant fraction_width : NATURAL := float_fraction_width) + return float is + variable result : float (exponent_width downto -fraction_width); + variable L : LINE; + variable good : BOOLEAN; + begin + L := new STRING'(hstring); + hread (L, result, good); + deallocate (L); + assert (good) + report "FLOAT_GENERIC_PKG.from_hstring: Bad string " & hstring + severity error; + return result; + end function from_hstring; + + function from_string ( + bstring : STRING; -- binary string + size_res : float) -- used for sizing only + return float is + begin + return from_string (bstring => bstring, + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function from_string; + + function from_ostring ( + ostring : STRING; -- Octal string + size_res : float) -- used for sizing only + return float is + begin + return from_ostring (ostring => ostring, + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function from_ostring; + + function from_hstring ( + hstring : STRING; -- hex string + size_res : float) -- used for sizing only + return float is + begin + return from_hstring (hstring => hstring, + exponent_width => size_res'high, + fraction_width => -size_res'low); + end function from_hstring; + -- synthesis translate_on +-- rtl_synthesis on + function to_StdLogicVector (arg : float) return STD_LOGIC_VECTOR is + begin + return to_slv (arg); + end function to_StdLogicVector; + + function to_Std_Logic_Vector (arg : float) return std_logic_vector is + begin + return to_slv (arg); + end function to_Std_Logic_Vector; + + function to_StdULogicVector (arg : float) return STD_ULOGIC_VECTOR is + begin + return to_sulv (arg); + end function to_StdULogicVector; + + function to_Std_ULogic_Vector (arg : float) return std_ulogic_vector is + begin + return to_sulv (arg); + end function to_Std_ULogic_Vector; +end package body float_pkg; diff --git a/lib/Standard/std/textio.vhdl b/lib/Standard/std/textio.vhdl new file mode 100644 index 0000000..71b3ca7 --- /dev/null +++ b/lib/Standard/std/textio.vhdl @@ -0,0 +1,130 @@ +-- Std.Textio package declaration. This file is part of GHDL. +-- This file was written from the clause 14.3 of the VHDL LRM. +-- Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold +-- +-- GHDL is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation; either version 2, or (at your option) any later +-- version. +-- +-- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or +-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with GCC; see the file COPYING. If not, write to the Free +-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. + +package textio is + +-- type definitions for text i/o + + -- a LINE is a pointer to a string value. + type line is access string; + + -- A file of variable-length ASCII records. + -- Note: in order to work correctly, the TEXT file type must be declared in + -- the textio package of library std. Otherwise, a file of string has a + -- non-ASCII format. + type text is file of string; + + type side is (right, left); -- For justifying ouput data within fields. + subtype width is natural; -- For specifying widths of output fields. + +-- standard text files + + file input: text is in "STD_INPUT"; --V87 + file output: text is out "STD_OUTPUT"; --V87 + file input : text open read_mode is "STD_INPUT"; --V93 + file output : text open write_mode is "STD_OUTPUT"; --V93 + +-- input routines for standard types + + procedure readline (variable f: in text; l: inout line); --V87 + procedure readline (file f: text; l: inout line); --V93 + + -- For READ procedures: + -- In this implementation, any L is accepted (ie, there is no constraints + -- on direction, or left bound). Therefore, even variable of type LINE + -- not initialized by READLINE are accepted. Strictly speaking, this is + -- not required by LRM, nor prevented. However, other implementations may + -- fail at parsing such strings. + -- + -- Also, in case of error (GOOD is false), this implementation do not + -- modify L (as specified by the LRM) nor VALUE. + -- + -- For READ procedures without a GOOD argument, an assertion fails in case + -- of error. + -- + -- In case of overflow (ie, if the number is out of the bounds of the type), + -- the procedure will fail with an execution error. + -- FIXME: this should not occur for a bad string. + + procedure read (l: inout line; value: out bit; good: out boolean); + procedure read (l: inout line; value: out bit); + + procedure read (l: inout line; value: out bit_vector; good: out boolean); + procedure read (l: inout line; value: out bit_vector); + + procedure read (l: inout line; value: out boolean; good: out boolean); + procedure read (l: inout line; value: out boolean); + + procedure read (l: inout line; value: out character; good: out boolean); + procedure read (l: inout line; value: out character); + + procedure read (l: inout line; value: out integer; good: out boolean); + procedure read (l: inout line; value: out integer); + + procedure read (l: inout line; value: out real; good: out boolean); + procedure read (l: inout line; value: out real); + + procedure read (l: inout line; value: out string; good: out boolean); + procedure read (l: inout line; value: out string); + + -- This implementation requires no space after the unit identifier, + -- ie "7.5 nsv" is parsed as 7.5 ns. + -- The unit identifier can be in lower case, upper case or mixed case. + procedure read (l: inout line; value: out time; good: out boolean); + procedure read (l: inout line; value: out time); + +-- output routines for standard types + + procedure writeline (variable f: out text; l: inout line); --V87 + procedure writeline (file f: text; l: inout line); --V93 + + -- This implementation accept any value for all the types. + procedure write + (l: inout line; value: in bit; + justified: in side := right; field: in width := 0); + procedure write + (l: inout line; value: in bit_vector; + justified: in side := right; field: in width := 0); + procedure write + (l: inout line; value: in boolean; + justified: in side := right; field: in width := 0); + procedure write + (l: inout line; value: in character; + justified: in side := right; field: in width := 0); + procedure write + (l: inout line; value: in integer; + justified: in side := right; field: in width := 0); + procedure write + (L: inout line; value: in real; + justified: in side := right; field: in width := 0; + digits: in natural := 0); + procedure write + (l: inout line; value: in string; + justified: in side := right; field: in width := 0); + + -- UNIT must be a unit name declared in std.standard. Of course, no rules + -- in the core VHDL language prevent you from using a value that is not a + -- unit (eg: 10 ns or even 5 fs). + -- An assertion error message is generated in this case, and question mark + -- (?) is written at the place of the unit name. + procedure write + (l: inout line; value : in time; + justified: in side := right; field: in width := 0; unit : in TIME := ns); + +end textio; diff --git a/lib/Standard/std/textio_body.vhdl b/lib/Standard/std/textio_body.vhdl new file mode 100644 index 0000000..1809adf --- /dev/null +++ b/lib/Standard/std/textio_body.vhdl @@ -0,0 +1,1326 @@ +-- Std.Textio package body. This file is part of GHDL. +-- Copyright (C) 2002, 2003, 2004, 2005 Tristan Gingold +-- +-- GHDL is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License as published by the Free +-- Software Foundation; either version 2, or (at your option) any later +-- version. +-- +-- GHDL is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or +-- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +-- for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with GCC; see the file COPYING. If not, write to the Free +-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA +-- 02111-1307, USA. + +package body textio is + -- output routines for standard types + + -- TIME_NAMES associates time units with textual names. + -- Textual names are in lower cases, since according to LRM93 14.3: + -- when written, the identifier is expressed in lowercase characters. + -- The length of the names are 3 characters, the last one may be a space + -- for 2 characters long names. + type time_unit is + record + val : time; + name : string (1 to 3); + end record; + type time_names_type is array (1 to 8) of time_unit; + constant time_names : time_names_type := + ((fs, "fs "), (ps, "ps "), (ns, "ns "), (us, "us "), + (ms, "ms "), (sec, "sec"), (min, "min"), (hr, "hr ")); + + -- Non breaking space character. --V93 + constant nbsp : character := character'val (160); --V93 + + procedure writeline (f: out text; l: inout line) is --V87 + procedure writeline (file f: text; l: inout line) is --V93 + begin + if l = null then + -- LRM93 14.3 + -- If parameter L contains a null access value at the start of the call, + -- the a null string is written to the file. + write (f, ""); + else + -- LRM93 14.3 + -- Procedure WRITELINE causes the current line designated by parameter L + -- to be written to the file and returns with the value of parameter L + -- designating a null string. + write (f, l.all); + deallocate (l); + l := new string'(""); + end if; + end writeline; + + procedure write + (l: inout line; value: in string; + justified: in side := right; field: in width := 0) + is + variable length: natural; + variable nl: line; + begin + -- l can be null. + if l = null then + length := 0; + else + length := l.all'length; + end if; + if value'length < field then + nl := new string (1 to length + field); + if length /= 0 then + nl (1 to length) := l.all; + end if; + if justified = right then + nl (length + 1 to length + field - value'length) := (others => ' '); + nl (nl.all'high - value'length + 1 to nl.all'high) := value; + else + nl (length + 1 to length + value'length) := value; + nl (length + value'length + 1 to nl.all'high) := (others => ' '); + end if; + else + nl := new string (1 to length + value'length); + if length /= 0 then + nl (1 to length) := l.all; + end if; + nl (length + 1 to nl.all'high) := value; + end if; + deallocate (l); + l := nl; + end write; + + procedure write + (l: inout line; value: in integer; + justified: in side := right; field: in width := 0) + is + variable str: string (11 downto 1); + variable val: integer := value; + variable digit: natural; + variable index: natural := 0; + begin + -- Note: the absolute value of VAL cannot be directly taken, since + -- it may be greather that the maximum value of an INTEGER. + loop + -- LRM93 7.2.6 + -- (A rem B) has the sign of A and an absolute value less then + -- the absoulte value of B. + digit := abs (val rem 10); + val := val / 10; + index := index + 1; + str (index) := character'val(48 + digit); + exit when val = 0; + end loop; + if value < 0 then + index := index + 1; + str(index) := '-'; + end if; + write (l, str (index downto 1), justified, field); + end write; + + procedure write + (l: inout line; value: in boolean; + justified: in side := right; field: in width := 0) + is + begin + if value then + write (l, string'("TRUE"), justified, field); + else + write (l, string'("FALSE"), justified, field); + end if; + end write; + + procedure write + (l: inout line; value: in character; + justified: in side := right; field: in width := 0) + is + variable str: string (1 to 1); + begin + str (1) := value; + write (l, str, justified, field); + end write; + + function bit_to_char (value : in bit) return character is + begin + case value is + when '0' => + return '0'; + when '1' => + return '1'; + end case; + end bit_to_char; + + procedure write + (l: inout line; value: in bit; + justified: in side := right; field: in width := 0) + is + variable str : string (1 to 1); + begin + str (1) := bit_to_char (value); + write (l, str, justified, field); + end write; + + procedure write + (l: inout line; value: in bit_vector; + justified: in side := right; field: in width := 0) + is + constant length : natural := value'length; + alias n_value : bit_vector (1 to value'length) is value; + variable str : string (1 to length); + begin + for i in str'range loop + str (i) := bit_to_char (n_value (i)); + end loop; + write (l, str, justified, field); + end write; + + procedure write + (l: inout line; value : in time; + justified: in side := right; field: in width := 0; unit : in TIME := ns) + is + -- Copy of VALUE on which we are working. + variable val : time := value; + + -- Copy of UNIT on which we are working. + variable un : time := unit; + + -- Digit extract from VAL/UN. + variable d : integer; -- natural range 0 to 9; + + -- Index for unit name. + variable n : integer; + + -- Result. + variable str : string (1 to 28); + + -- Current character in RES. + variable pos : natural := 1; + + -- Add a character to STR. + procedure add_char (c : character) is + begin + str (pos) := c; + pos := pos + 1; + end add_char; + begin + -- Note: + -- Care is taken to avoid overflow. Time may be 64 bits while integer + -- may be only 32 bits. + + -- Handle sign. + -- Note: VAL cannot be negated since its range may be not symetric + -- around 0. + if val < 0 ns then + add_char ('-'); + end if; + + -- Search for the first digit. + -- Note: we must start from unit, since all units are not a power of 10. + -- Note: UN can be multiplied only after we know it is possible. This + -- is a to avoid overflow. + if un <= 0 fs then + assert false report "UNIT argument is not positive" severity error; + un := 1 ns; + end if; + while val / 10 >= un or val / 10 <= -un loop + un := un * 10; + end loop; + + -- Extract digits one per one. + loop + d := val / un; + add_char (character'val (abs d + character'pos ('0'))); + val := val - d * un; + exit when val = 0 ns and un <= unit; + if un = unit then + add_char ('.'); + end if; + -- Stop as soon as precision will be lost. + -- This can happen only for hr and min. + -- FIXME: change the algorithm to display all the digits. + exit when (un / 10) * 10 /= un; + un := un / 10; + end loop; + + add_char (' '); + + -- Search the time unit name in the time table. + n := 0; + for i in time_names'range loop + if time_names (i).val = unit then + n := i; + exit; + end if; + end loop; + assert n /= 0 report "UNIT argument is not a unit name" severity error; + if n = 0 then + add_char ('?'); + else + add_char (time_names (n).name (1)); + add_char (time_names (n).name (2)); + if time_names (n).name (3) /= ' ' then + add_char (time_names (n).name (3)); + end if; + end if; + + -- Write the result. + write (l, str (1 to pos - 1), justified, field); + end write; + + -- Parameter DIGITS specifies how many digits to the right of the decimal + -- point are to be output when writing a real number; the default value 0 + -- indicates that the number should be output in standard form, consisting + -- of a normalized mantissa plus exponent (e.g., 1.079236E23). If DIGITS is + -- nonzero, then the real number is output as an integer part followed by + -- '.' followed by the fractional part, using the specified number of digits + -- (e.g., 3.14159). + -- Note: Nan, +Inf, -Inf are not to be considered, since these numbers are + -- not in the bounds defined by any real range. + procedure write (L: inout line; value: in real; + justified: in side := right; field: in width := 0; + digits: in natural := 0) + is + -- STR contains the result of the conversion. + variable str : string (1 to 320); + + -- POS is the index of the next character to be put in STR. + variable pos : positive := str'left; + + -- VAL contains the value to be converted. + variable val : real; + + -- The exponent or mantissa computed is stored in MANTISSA. This is + -- a signed number. + variable mantissa : integer; + + variable b : boolean; + variable d : natural; + + -- Append character C in STR. + procedure add_char (c : character) is + begin + str (pos) := c; + pos := pos + 1; + end add_char; + + -- Add digit V in STR. + procedure add_digit (v : natural) is + begin + add_char (character'val (character'pos ('0') + v)); + end add_digit; + + -- Add leading digit and substract it. + procedure extract_leading_digit is + variable d : natural range 0 to 10; + begin + -- Note: We need truncation but type conversion does rounding. + -- FIXME: should consider precision. + d := natural (val); + if real (d) > val then + d := d - 1; + end if; + + val := (val - real (d)) * 10.0; + + add_digit (d); + end extract_leading_digit; + begin + -- Handle sign. + -- There is no overflow here, since with IEEE implementations, sign is + -- independant of the mantissa. + -- LRM93 14.3 + -- The sign is never written if the value is non-negative. + if value < 0.0 then + add_char ('-'); + val := -value; + else + val := value; + end if; + + -- Compute the mantissa. + -- FIXME: should do a dichotomy. + if val = 0.0 then + mantissa := 0; + elsif val < 1.0 then + mantissa := -1; + while val * (10.0 ** (-mantissa)) < 1.0 loop + mantissa := mantissa - 1; + end loop; + else + mantissa := 0; + while val / (10.0 ** mantissa) >= 10.0 loop + mantissa := mantissa + 1; + end loop; + end if; + + -- Normalize VAL: in [0; 10[ + if mantissa >= 0 then + val := val / (10.0 ** mantissa); + else + val := val * 10.0 ** (-mantissa); + end if; + + if digits = 0 then + for i in 0 to 15 loop + extract_leading_digit; + + if i = 0 then + add_char ('.'); + end if; + exit when i > 0 and val < 10.0 ** (i + 1 - 15); + end loop; + + -- LRM93 14.3 + -- if the exponent is present, the `e' is written as a lower case + -- character. + add_char ('e'); + + if mantissa < 0 then + add_char ('-'); + mantissa := -mantissa; + end if; + b := false; + for i in 4 downto 0 loop + d := (mantissa / 10000) mod 10; + if d /= 0 or b or i = 0 then + add_digit (d); + b := true; + end if; + mantissa := (mantissa - d * 10000) * 10; + end loop; + else + if mantissa < 0 then + add_char ('0'); + mantissa := mantissa + 1; + else + loop + extract_leading_digit; + exit when mantissa = 0; + mantissa := mantissa - 1; + end loop; + end if; + add_char ('.'); + for i in 1 to digits loop + if mantissa = 0 then + extract_leading_digit; + else + add_char ('0'); + mantissa := mantissa + 1; + end if; + end loop; + end if; + write (l, str (1 to pos - 1), justified, field); + end write; + + procedure untruncated_text_read --V87 + (variable f : text; str : out string; len : out natural); --V87 + procedure untruncated_text_read --V93 + (file f : text; str : out string; len : out natural); --V93 + + attribute foreign : string; --V87 + attribute foreign of untruncated_text_read : procedure is "GHDL intrinsic"; + + procedure untruncated_text_read + (variable f : text; str : out string; len : out natural) is --V87 + (file f : text; str : out string; len : out natural) is --V93 + begin + assert false report "must not be called" severity failure; + end untruncated_text_read; + + procedure readline (variable f: in text; l: inout line) --V87 + procedure readline (file f: text; l: inout line) --V93 + is + variable len, nlen, posn : natural; + variable nl, old_l : line; + variable str : string (1 to 128); + variable is_eol : boolean; + begin + -- LRM93 14.3 + -- If parameter L contains a non-null access value at the start of the + -- call, the object designated by that value is deallocated before the + -- new object is created. + if l /= null then + deallocate (l); + end if; + + -- We read the input in 128-byte chunks. + -- We keep reading until we reach a newline or there is no more input. + -- The loop invariant is that old_l is allocated and contains the + -- previous chunks read, and posn = old_l.all'length. + posn := 0; + loop + untruncated_text_read (f, str, len); + exit when len = 0; + if str (len) = LF or str (len) = CR then + -- LRM 14.3 + -- The representation of the line does not contain the representation + -- of the end of the line. + is_eol := true; + len := len - 1; + -- End of line is any of LF/CR/CR+LF/LF+CR. + if len > 0 and (str (len) = LF or str (len) = CR) then + len := len - 1; + end if; + elsif endfile (f) then + is_eol := true; + else + is_eol := false; + end if; + l := new string (1 to posn + len); + if old_l /= null then + l (1 to posn) := old_l (1 to posn); + deallocate (old_l); + end if; + l (posn + 1 to posn + len) := str (1 to len); + exit when is_eol; + posn := posn + len; + old_l := l; + end loop; + end readline; + + -- Replaces L with L (LEFT to/downto L'RIGHT) + procedure trim (l : inout line; left : natural) + is + variable nl : line; + begin + if l = null then + return; + end if; + if l'left < l'right then + -- Ascending. + if left > l'right then + nl := new string'(""); + else + nl := new string (left to l'right); +-- nl := new string (1 to l'right + 1 - left); + nl.all := l (left to l'right); + end if; + else + -- Descending + if left < l'right then + nl := new string'(""); + else + nl := new string (left downto l'right); +-- nl := new string (left - l'right + 1 downto 1); + nl.all := l (left downto l'right); + end if; + end if; + deallocate (l); + l := nl; + end trim; + + -- Replaces L with L (LEFT + 1 to L'RIGHT or LEFT - 1 downto L'RIGHT) + procedure trim_next (l : inout line; left : natural) + is + variable nl : line; + begin + if l = null then + return; + end if; + if l'left < l'right then + -- Ascending. + trim (l, left + 1); + else + -- Descending + trim (l, left - 1); + end if; + end trim_next; + + function to_lower (c : character) return character is + begin + if c >= 'A' and c <= 'Z' then + return character'val (character'pos (c) + 32); + else + return c; + end if; + end to_lower; + + procedure read (l: inout line; value: out character; good: out boolean) + is + variable nl : line; + begin + if l = null or l'length = 0 then + good := false; + else + value := l (l'left); + trim_next (l, l'left); + good := true; + end if; + end read; + + procedure read (l: inout line; value: out character) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "character read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out bit; good: out boolean) + is + begin + good := false; + for i in l'range loop + case l(i) is + when ' ' + | NBSP --V93 + | HT => + null; + when '1' => + value := '1'; + good := true; + trim_next (l, i); + return; + when '0' => + value := '0'; + good := true; + trim_next (l, i); + return; + when others => + return; + end case; + end loop; + return; + end read; + + procedure read (l: inout line; value: out bit) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "bit read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out bit_vector; good: out boolean) + is + -- Number of bit to parse. + variable len : natural; + + variable pos, last : natural; + variable res : bit_vector (1 to value'length); + + -- State of the previous byte: + -- LEADING: blank before the bit vector. + -- FOUND: bit of the vector. + type state_type is (leading, found); + variable state : state_type; + begin + -- Initialization. + len := value'length; + if len = 0 then + -- If VALUE is a nul array, return now. + -- L stay unchanged. + -- FIXME: should blanks be removed ? + good := true; + return; + end if; + good := false; + state := leading; + pos := res'left; + for i in l'range loop + case l(i) is + when ' ' + | NBSP --V93 + | HT => + case state is + when leading => + null; + when found => + return; + end case; + when '1' | '0' => + case state is + when leading => + state := found; + when found => + null; + end case; + if l(i) = '0' then + res (pos) := '0'; + else + res (pos) := '1'; + end if; + pos := pos + 1; + len := len - 1; + last := i; + exit when len = 0; + when others => + return; + end case; + end loop; + + if len /= 0 then + -- Not enough bits. + return; + end if; + + -- Note: if LEN = 0, then FIRST and LAST have been set. + good := true; + value := res; + trim_next (l, last); + return; + end read; + + procedure read (l: inout line; value: out bit_vector) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "bit_vector read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out boolean; good: out boolean) + is + -- State: + -- BLANK: space are being scaned. + -- L_TF : T(rue) or F(alse) has been scanned. + -- L_RA : (t)R(ue) or (f)A(lse) has been scanned. + -- L_UL : (tr)U(e) or (fa)L(se) has been scanned. + -- L_ES : (tru)E or (fal)S(e) has been scanned. + type state_type is (blank, l_tf, l_ra, l_ul, l_es); + variable state : state_type; + + -- Set to TRUE if T has been scanned, to FALSE if F has been scanned. + variable res : boolean; + begin + -- By default, it is a failure. + good := false; + state := blank; + for i in l'range loop + case state is + when blank => + if l (i) = ' ' + or l (i) = nbsp --V93 + or l (i) = HT + then + null; + elsif to_lower (l (i)) = 't' then + res := true; + state := l_tf; + elsif to_lower (l (i)) = 'f' then + res := false; + state := l_tf; + else + return; + end if; + when l_tf => + if res = true and to_lower (l (i)) = 'r' then + state := l_ra; + elsif res = false and to_lower (l (i)) = 'a' then + state := l_ra; + else + return; + end if; + when l_ra => + if res = true and to_lower (l (i)) = 'u' then + state := l_ul; + elsif res = false and to_lower (l (i)) = 'l' then + state := l_ul; + else + return; + end if; + when l_ul => + if res = true and to_lower (l (i)) = 'e' then + trim_next (l, i); + good := true; + value := true; + return; + elsif res = false and to_lower (l (i)) = 's' then + state := l_es; + else + return; + end if; + when l_es => + if res = false and to_lower (l (i)) = 'e' then + trim_next (l, i); + good := true; + value := false; + return; + else + return; + end if; + end case; + end loop; + return; + end read; + + procedure read (l: inout line; value: out boolean) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "boolean read failure" + severity failure; + end read; + + function char_to_nat (c : character) return natural + is + begin + return character'pos (c) - character'pos ('0'); + end char_to_nat; + + procedure read (l: inout line; value: out integer; good: out boolean) + is + variable val : integer; + variable d : natural; + + type state_t is (leading, sign, digits); + variable cur_state : state_t := leading; + begin + val := 1; + for i in l'range loop + case cur_state is + when leading => + case l(i) is + when ' ' + | NBSP --V93 + | ht => + null; + when '+' => + cur_state := sign; + when '-' => + val := -1; + cur_state := sign; + when '0' to '9' => + val := char_to_nat (l(i)); + cur_state := digits; + when others => + good := false; + return; + end case; + when sign => + case l(i) is + when '0' to '9' => + val := val * char_to_nat (l(i)); + cur_state := digits; + when others => + good := false; + return; + end case; + when digits => + case l(i) is + when '0' to '9' => + d := char_to_nat (l(i)); + val := val * 10; + if val < 0 then + val := val - d; + else + val := val + d; + end if; + when others => + trim (l, i); + good := true; + value := val; + return; + end case; + end case; + end loop; + deallocate (l); + l := new string'(""); + if cur_state /= leading then + good := true; + value := val; + else + good := false; + end if; + end read; + + procedure read (l: inout line; value: out integer) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "integer read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out real; good: out boolean) + is + -- The result. + variable val : real; + -- True if the result is negative. + variable val_neg : boolean; + + -- Number of digits after the dot. + variable nbr_dec : natural; + + -- Value of the exponent. + variable exp : integer; + -- True if the exponent is negative. + variable exp_neg : boolean; + + -- The parsing is done with a state machine. + -- LEADING: leading blank suppression. + -- SIGN: a sign has been found. + -- DIGITS: integer parts + -- DECIMALS: digits after the dot. + -- EXPONENT_SIGN: sign after "E" + -- EXPONENT_1: first digit of the exponent. + -- EXPONENT: digits of the exponent. + type state_t is (leading, sign, digits, decimals, + exponent_sign, exponent_1, exponent); + variable cur_state : state_t := leading; + + -- Set VALUE to the result, and set GOOD to TRUE. + procedure set_value is + begin + good := true; + + if exp_neg then + val := val * 10.0 ** (-exp); + else + val := val * 10.0 ** exp; + end if; + if val_neg then + value := -val; + else + value := val; + end if; + end set_value; + + begin + -- Initialization. + val_neg := false; + nbr_dec := 1; + exp := 0; + exp_neg := false; + + -- By default, parsing has failed. + good := false; + + -- Iterate over all characters of the string. + -- Return immediatly in case of parse error. + -- Trim L and call SET_VALUE and return in case of success. + for i in l'range loop + case cur_state is + when leading => + case l(i) is + when ' ' + | NBSP --V93 + | ht => + null; + when '+' => + cur_state := sign; + when '-' => + val_neg := true; + cur_state := sign; + when '0' to '9' => + val := real (char_to_nat (l(i))); + cur_state := digits; + when others => + return; + end case; + when sign => + case l(i) is + when '0' to '9' => + val := real (char_to_nat (l(i))); + cur_state := digits; + when others => + return; + end case; + when digits => + case l(i) is + when '0' to '9' => + val := val * 10.0 + real (char_to_nat (l(i))); + when '.' => + cur_state := decimals; + when others => + -- A "." (dot) is required in the string. + return; + end case; + when decimals => + case l(i) is + when '0' to '9' => + val := val + real (char_to_nat (l(i))) / (10.0 ** nbr_dec); + nbr_dec := nbr_dec + 1; + when 'e' | 'E' => + -- "nnn.E" is erroneous. + if nbr_dec = 1 then + return; + end if; + cur_state := exponent_sign; + when others => + -- "nnn.XX" is erroneous. + if nbr_dec = 1 then + return; + end if; + trim (l, i); + set_value; + return; + end case; + when exponent_sign => + case l(i) is + when '+' => + cur_state := exponent_1; + when '-' => + exp_neg := true; + cur_state := exponent_1; + when '0' to '9' => + exp := char_to_nat (l(i)); + cur_state := exponent; + when others => + -- Error. + return; + end case; + when exponent_1 | exponent => + case l(i) is + when '0' to '9' => + exp := exp * 10 + char_to_nat (l(i)); + cur_state := exponent; + when others => + trim (l, i); + set_value; + return; + end case; + end case; + end loop; + + -- End of string. + case cur_state is + when leading | sign | digits => + -- Erroneous. + return; + when decimals => + -- "nnn.XX" is erroneous. + if nbr_dec = 1 then + return; + end if; + when exponent_sign => + -- Erroneous ("NNN.NNNE") + return; + when exponent_1 => + -- "NNN.NNNE-" + return; + when exponent => + null; + end case; + + deallocate (l); + l := new string'(""); + set_value; + end read; + + procedure read (l: inout line; value: out real) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "real read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out time; good: out boolean) + is + -- The result. + variable res : time; + + -- UNIT is computed from the unit name, the exponent and the number of + -- digits before the dot. UNIT is the weight of the current digit. + variable unit : time; + + -- Number of digits before the dot. + variable nbr_digits : integer; + + -- True if a unit name has been found. Used temporaly to know the status + -- at the end of the search loop. + variable unit_found : boolean; + + -- True if the number is negative. + variable is_neg : boolean; + + -- Value of the exponent. + variable exp : integer; + + -- True if the exponent is negative. + variable exp_neg : boolean; + + -- Unit name extracted from the string. + variable unit_name : string (1 to 3); + + -- state is the kind of the previous character parsed. + -- LEADING: leading blanks + -- SIGN: + or - as the first character of the number. + -- DIGITS: digit of the integer part of the number. + -- DOT: dot (.) after the integer part and before the decimal part. + -- DECIMALS: digit of the decimal part. + -- EXPONENT_MARK: e or E. + -- EXPONENT_SIGN: + or - just after the exponent mark (E). + -- EXPONENT: digit of the exponent. + -- UNIT_BLANK: blank after the exponent. + -- UNIT_1, UNIT_2, UNIT_3: first, second, third character of the unit. + type state_type is (leading, sign, digits, dot, decimals, + exponent_mark, exponent_sign, exponent, + unit_blank, unit_1, unit_2, unit_3); + variable state : state_type; + + -- Used during the second scan of the string, TRUE is digits is being + -- scaned. + variable has_digits : boolean; + + -- Position at the end of the string. + variable pos : integer; + + -- Used to compute POS. + variable length : integer; + begin + -- Initialization. + -- Fail by default; therefore, in case of error, a return statement is + -- ok. + good := false; + + nbr_digits := 0; + is_neg := false; + exp := 0; + exp_neg := false; + res := 0 fs; + + -- Look for exponent and unit name. + -- Parse the string: this loop checks the correctness of the format, and + -- must return (GOOD has been set to FALSE) in case of error. + -- Set: NBR_DIGITS, IS_NEG, EXP, EXP_NEG. + state := leading; + for i in l'range loop + case l (i) is + when ' ' + | NBSP --V93 + | HT => + case state is + when leading | unit_blank => + null; + when sign | dot | exponent_mark | exponent_sign => + return; + when digits | decimals | exponent => + state := unit_blank; + when unit_1 | unit_2 => + exit; + when unit_3 => + -- Cannot happen, since an exit is performed at unit_3. + assert false report "internal error" severity failure; + end case; + when '+' | '-' => + case state is + when leading => + if l(i) = '-' then + is_neg := true; + end if; + state := sign; + when exponent_mark => + if l(i) = '-' then + exp_neg := true; + end if; + state := exponent_sign; + when others => + return; + end case; + when '0' to '9' => + case state is + when exponent_mark | exponent_sign | exponent => + exp := exp * 10 + char_to_nat (l (i)); + state := exponent; + when leading | sign | digits => + -- Leading "0" are not significant. + if nbr_digits > 0 or l (i) /= '0' then + nbr_digits := nbr_digits + 1; + end if; + state := digits; + when decimals => + null; + when dot => + state := decimals; + when others => + return; + end case; + when 'a' to 'z' | 'A' to 'Z' => + case state is + when digits | decimals => + -- "E" has exponent mark. + if l (i) = 'e' or l(i) = 'E' then + state := exponent_mark; + else + return; + end if; + when unit_blank => + unit_name (1) := to_lower (l(i)); + state := unit_1; + when unit_1 => + unit_name (2) := to_lower (l(i)); + state := unit_2; + pos := i; + when unit_2 => + unit_name (3) := to_lower (l(i)); + state := unit_3; + exit; + when others => + return; + end case; + when '.' => + case state is + when digits => + state := decimals; + when others => + exit; + end case; + when others => + exit; + end case; + end loop; + + -- A unit name (2 or 3 letters) must have been found. + -- The string may end anywhere. + if state /= unit_2 and state /= unit_3 then + return; + end if; + + -- Compute EXP with the sign. + if exp_neg then + exp := -exp; + end if; + + -- Search the unit name in the list of time names. + unit_found := false; + for i in time_names'range loop + -- The first two characters must match (case insensitive). + -- The third character must match if: + -- * the unit name is a three characters identifier (ie, not a blank). + -- * there is a third character in STR. + if time_names (i).name (1) = unit_name (1) + and time_names (i).name (2) = unit_name (2) + and (time_names (i).name (3) = ' ' + or time_names (i).name (3) = unit_name (3)) + then + unit := time_names (i).val; + unit_found := true; + -- POS is set to the position of the first invalid character. + if time_names (i).name (3) = ' ' then + length := 1; + else + length := 2; + end if; + if l'left < l'right then + pos := pos + length; + else + pos := pos - length; + end if; + exit; + end if; + end loop; + if not unit_found then + return; + end if; + + -- Compute UNIT, the weight of the first non-significant character. + nbr_digits := nbr_digits + exp - 1; + if nbr_digits < 0 then + unit := unit / 10 ** (-nbr_digits); + else + unit := unit * 10 ** nbr_digits; + end if; + + -- HAS_DIGITS will be set as soon as a digit is found. + -- No error is expected here (this has been checked during the first + -- pass). + has_digits := false; + for i in l'range loop + case l (i) is + when ' ' + | NBSP --V93 + | HT => + if has_digits then + exit; + end if; + when '+' | '-' => + if not has_digits then + has_digits := true; + else + assert false report "internal error" severity failure; + return; + end if; + when '0' to '9' => + -- Leading "0" are not significant. + if l (i) /= '0' or res /= 0 fs then + res := res + char_to_nat (l (i)) * unit; + unit := unit / 10; + end if; + has_digits := true; + when 'a' to 'z' | 'A' to 'Z' => + if has_digits then + exit; + else + assert false report "internal error" severity failure; + return; + end if; + when '.' => + if not has_digits then + assert false report "internal error" severity failure; + return; + end if; + when others => + assert false report "internal error" severity failure; + return; + end case; + end loop; + + -- Set VALUE. + if is_neg then + value := -res; + else + value := res; + end if; + good := true; + trim (l, pos); + return; + end read; + + procedure read (l: inout line; value: out time) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "time read failure" + severity failure; + end read; + + procedure read (l: inout line; value: out string; good: out boolean) + is + constant len : natural := value'length; + begin + if l'length < len then + good := false; + return; + end if; + good := true; + if len = 0 then + return; + end if; + if l'left < l'right then + value := l (l'left to l'left + len - 1); + trim (l, l'left + len); + else + value := l (l'left downto l'left - len + 1); + trim (l, l'left - len); + end if; + end read; + + procedure read (l: inout line; value: out string) + is + variable res : boolean; + begin + read (l, value, res); + assert res = true + report "string read failure" + severity failure; + end read; + +end textio; diff --git a/lib/Standard/synopsys/std_logic_arith.vhd b/lib/Standard/synopsys/std_logic_arith.vhd new file mode 100644 index 0000000..ffa3937 --- /dev/null +++ b/lib/Standard/synopsys/std_logic_arith.vhd @@ -0,0 +1,2399 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990,1991,1992 by Synopsys, Inc. All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_ARITH -- +-- -- +-- Purpose: -- +-- A set of arithemtic, conversion, and comparison functions -- +-- for SIGNED, UNSIGNED, SMALL_INT, INTEGER, -- +-- STD_ULOGIC, STD_LOGIC, and STD_LOGIC_VECTOR. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; + +package std_logic_arith is + + type UNSIGNED is array (NATURAL range <>) of STD_LOGIC; + type SIGNED is array (NATURAL range <>) of STD_LOGIC; + subtype SMALL_INT is INTEGER range 0 to 1; + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: INTEGER) return SIGNED; + function "+"(L: INTEGER; R: SIGNED) return SIGNED; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED; + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED; + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: INTEGER) return SIGNED; + function "-"(L: INTEGER; R: SIGNED) return SIGNED; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED; + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED; + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED; + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR; + + function "+"(L: UNSIGNED) return UNSIGNED; + function "+"(L: SIGNED) return SIGNED; + function "-"(L: SIGNED) return SIGNED; + function "ABS"(L: SIGNED) return SIGNED; + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR; + function "+"(L: SIGNED) return STD_LOGIC_VECTOR; + function "-"(L: SIGNED) return STD_LOGIC_VECTOR; + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED; + function "*"(L: SIGNED; R: SIGNED) return SIGNED; + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED; + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR; + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR; + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN; + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN; + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN; + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN; + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED; + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED; + + function CONV_INTEGER(ARG: INTEGER) return INTEGER; + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER; + function CONV_INTEGER(ARG: SIGNED) return INTEGER; + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT; + + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED; + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED; + + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED; + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED; + + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) + return STD_LOGIC_VECTOR; + -- zero extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- returns STD_LOGIC_VECTOR(SIZE-1 downto 0) + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + + -- sign extend STD_LOGIC_VECTOR (ARG) to SIZE, + -- SIZE < 0 is same as SIZE = 0 + -- return STD_LOGIC_VECTOR(SIZE-1 downto 0) + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end Std_logic_arith; + + + +library IEEE; +use IEEE.std_logic_1164.all; + +package body std_logic_arith is + + function max(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function min(L, R: INTEGER) return INTEGER is + begin + if L < R then + return L; + else + return R; + end if; + end; + + -- synopsys synthesis_off + type tbl_type is array (STD_ULOGIC) of STD_ULOGIC; + constant tbl_BINARY : tbl_type := + ('X', 'X', '0', '1', 'X', 'X', '0', '1', 'X'); + -- synopsys synthesis_on + + -- synopsys synthesis_off + type tbl_mvl9_boolean is array (STD_ULOGIC) of boolean; + constant IS_X : tbl_mvl9_boolean := + (true, true, false, false, true, true, false, false, true); + -- synopsys synthesis_on + + + + function MAKE_BINARY(A : STD_ULOGIC) return STD_ULOGIC is + -- synopsys built_in SYN_FEED_THRU + begin + -- synopsys synthesis_off + if (IS_X(A)) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + return ('X'); + end if; + return tbl_BINARY(A); + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return UNSIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : UNSIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return SIGNED is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : SIGNED (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + function MAKE_BINARY(A : SIGNED) return STD_LOGIC_VECTOR is + -- synopsys built_in SYN_FEED_THRU + variable one_bit : STD_ULOGIC; + variable result : STD_LOGIC_VECTOR (A'range); + begin + -- synopsys synthesis_off + for i in A'range loop + if (IS_X(A(i))) then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + result := (others => 'X'); + return result; + end if; + result(i) := tbl_BINARY(A(i)); + end loop; + return result; + -- synopsys synthesis_on + end; + + + + -- Type propagation function which returns a signed type with the + -- size of the left arg. + function LEFT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the left arg. + function LEFT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED (A'left downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns a signed type with the + -- size of the result of a signed multiplication + function MULT_SIGNED_ARG(A,B: SIGNED) return SIGNED is + variable Z: SIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns an unsigned type with the + -- size of the result of a unsigned multiplication + function MULT_UNSIGNED_ARG(A,B: UNSIGNED) return UNSIGNED is + variable Z: UNSIGNED ((A'length+B'length-1) downto 0); + -- pragma return_port_name Z + begin + return(Z); + end; + + + + function mult(A,B: SIGNED) return SIGNED is + + variable BA: SIGNED((A'length+B'length-1) downto 0); + variable PA: SIGNED((A'length+B'length-1) downto 0); + variable AA: SIGNED(A'length downto 0); + variable neg: STD_ULOGIC; + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_TC_OP + -- pragma type_function MULT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + neg := B(B'left) xor A(A'left); + BA := CONV_SIGNED(('0' & ABS(B)),(A'length+B'length)); + AA := '0' & ABS(A); + for i in 0 to A'length-1 loop + if AA(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + if (neg= '1') then + return(-PA); + else + return(PA); + end if; + end; + + function mult(A,B: UNSIGNED) return UNSIGNED is + + variable BA: UNSIGNED((A'length+B'length-1) downto 0); + variable PA: UNSIGNED((A'length+B'length-1) downto 0); + constant one : UNSIGNED(1 downto 0) := "01"; + + -- pragma map_to_operator MULT_UNS_OP + -- pragma type_function MULT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + PA := (others => 'X'); + return(PA); + end if; + PA := (others => '0'); + BA := CONV_UNSIGNED(B,(A'length+B'length)); + for i in 0 to A'length-1 loop + if A(i) = '1' then + PA := PA+BA; + end if; + BA := SHL(BA,one); + end loop; + return(PA); + end; + + -- subtract two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function minus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_TC_OP + + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function plus(A, B: SIGNED) return SIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: SIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_TC_OP + -- pragma type_function LEFT_SIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + -- subtract two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_minus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV: STD_ULOGIC_VECTOR (A'left downto 0); + variable sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator SUB_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '1'; + BV := not STD_ULOGIC_VECTOR(B); + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + -- add two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is + variable carry: STD_ULOGIC; + variable BV, sum: UNSIGNED (A'left downto 0); + + -- pragma map_to_operator ADD_UNS_OP + -- pragma type_function LEFT_UNSIGNED_ARG + -- pragma return_port_name Z + + begin + if (A(A'left) = 'X' or B(B'left) = 'X') then + sum := (others => 'X'); + return(sum); + end if; + carry := '0'; + BV := B; + + for i in 0 to A'left loop + sum(i) := A(i) xor BV(i) xor carry; + carry := (A(i) and BV(i)) or + (A(i) and carry) or + (carry and BV(i)); + end loop; + return sum; + end; + + + + function "*"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 296 + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 295 + begin + return mult(CONV_UNSIGNED(L, L'length), + CONV_UNSIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 297 + begin + return mult(CONV_SIGNED(L, L'length+1), + CONV_SIGNED(R, R'length)); -- pragma label mult + end; + + function "*"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to mult + -- synopsys subpgm_id 298 + begin + return mult(CONV_SIGNED(L, L'length), + CONV_SIGNED(R, R'length+1)); -- pragma label mult + end; + + + function "*"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 301 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length), CONV_SIGNED(R, R'length))); + end; + + function "*"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 300 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_UNSIGNED(L, L'length), CONV_UNSIGNED(R, R'length))); + end; + + function "*"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 302 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length+1), CONV_SIGNED(R, R'length))); + end; + + function "*"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + -- synopsys subpgm_id 303 + begin + return STD_LOGIC_VECTOR ( + mult(-- pragma label mult + CONV_SIGNED(L, L'length), CONV_SIGNED(R, R'length+1))); + end; + + + function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 236 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 237 + constant length: INTEGER := max(L'length, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 238 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 239 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 240 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 241 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "+"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 242 + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 243 + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 244 + constant length: INTEGER := L'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)) ; -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 245 + constant length: INTEGER := R'length; + begin + return unsigned_plus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 246 + constant length: INTEGER := L'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to plus + -- synopsys subpgm_id 247 + constant length: INTEGER := R'length; + begin + return plus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label plus + end; + + + + function "+"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 260 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 261 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 262 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 263 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 264 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "+"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 265 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + plus( -- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "+"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 266 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 267 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 268 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))) ; + end; + + + function "+"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 269 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + unsigned_plus(-- pragma label plus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "+"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 270 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "+"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + -- synopsys subpgm_id 271 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + plus(-- pragma label plus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 248 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_minus(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 249 + constant length: INTEGER := max(L'length, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 250 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 251 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 252 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 253 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: SIGNED; R: INTEGER) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 254 + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: INTEGER; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 255 + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 256 + constant length: INTEGER := L'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return UNSIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 257 + constant length: INTEGER := R'length + 1; + begin + return CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 258 + constant length: INTEGER := L'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 259 + constant length: INTEGER := R'length; + begin + return minus(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label minus + end; + + + + + function "-"(L: UNSIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 272 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + unsigned_minus(-- pragma label minus + CONV_UNSIGNED(L, length), CONV_UNSIGNED(R, length))); + end; + + + function "-"(L: SIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 273 + constant length: INTEGER := max(L'length, R'length); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 274 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: SIGNED; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 275 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 276 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: INTEGER; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 277 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: SIGNED; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 278 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: INTEGER; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 279 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: UNSIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 280 + constant length: INTEGER := L'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: STD_ULOGIC; R: UNSIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 281 + constant length: INTEGER := R'length + 1; + begin + return STD_LOGIC_VECTOR (CONV_UNSIGNED( + minus( -- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length)), length-1)); + end; + + + function "-"(L: SIGNED; R: STD_ULOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 282 + constant length: INTEGER := L'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + function "-"(L: STD_ULOGIC; R: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 283 + constant length: INTEGER := R'length; + begin + return STD_LOGIC_VECTOR ( + minus(-- pragma label minus + CONV_SIGNED(L, length), CONV_SIGNED(R, length))); + end; + + + + + function "+"(L: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 284 + begin + return L; + end; + + + function "+"(L: SIGNED) return SIGNED is + -- synopsys subpgm_id 285 + begin + return L; + end; + + + function "-"(L: SIGNED) return SIGNED is + -- pragma label_applies_to minus + -- synopsys subpgm_id 286 + begin + return 0 - L; -- pragma label minus + end; + + + function "ABS"(L: SIGNED) return SIGNED is + -- synopsys subpgm_id 287 + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return L; + else + return 0 - L; + end if; + end; + + + function "+"(L: UNSIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 289 + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "+"(L: SIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 290 + begin + return STD_LOGIC_VECTOR (L); + end; + + + function "-"(L: SIGNED) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + -- synopsys subpgm_id 292 + variable tmp: SIGNED(L'length-1 downto 0); + begin + tmp := 0 - L; -- pragma label minus + return STD_LOGIC_VECTOR (tmp); + end; + + + function "ABS"(L: SIGNED) return STD_LOGIC_VECTOR is + -- synopsys subpgm_id 294 + variable tmp: SIGNED(L'length-1 downto 0); + begin + if (L(L'left) = '0' or L(L'left) = 'L') then + return STD_LOGIC_VECTOR (L); + else + tmp := 0 - L; + return STD_LOGIC_VECTOR (tmp); + end if; + end; + + + -- Type propagation function which returns the type BOOLEAN + function UNSIGNED_RETURN_BOOLEAN(A,B: UNSIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + -- Type propagation function which returns the type BOOLEAN + function SIGNED_RETURN_BOOLEAN(A,B: SIGNED) return BOOLEAN is + variable Z: BOOLEAN; + -- pragma return_port_name Z + begin + return(Z); + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := FALSE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + -- compare two signed numbers of the same length + -- both arrays must have range (msb downto 0) + function is_less_or_equal(A, B: SIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_TC_OP + -- pragma type_function SIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + if A(sign) /= B(sign) then + result := A(sign) = '1'; + else + result := TRUE; + for i in 0 to sign-1 loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + end if; + return result; + end; + + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LT_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := FALSE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + -- compare two unsigned numbers of the same length + -- both arrays must have range (msb downto 0) + function unsigned_is_less_or_equal(A, B: UNSIGNED) return BOOLEAN is + constant sign: INTEGER := A'left; + variable a_is_0, b_is_1, result : boolean; + + -- pragma map_to_operator LEQ_UNS_OP + -- pragma type_function UNSIGNED_RETURN_BOOLEAN + -- pragma return_port_name Z + + begin + result := TRUE; + for i in 0 to sign loop + a_is_0 := A(i) = '0'; + b_is_1 := B(i) = '1'; + result := (a_is_0 and b_is_1) or + (a_is_0 and result) or + (b_is_1 and result); + end loop; + return result; + end; + + + + + function "<"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 305 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 306 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 307 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 308 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 309 + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 310 + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 311 + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + function "<"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to lt + -- synopsys subpgm_id 312 + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label lt + end; + + + + + function "<="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 314 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(L, length), + CONV_UNSIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 315 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 316 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 317 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 318 + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 319 + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 320 + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + function "<="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to leq + -- synopsys subpgm_id 321 + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(L, length), + CONV_SIGNED(R, length)); -- pragma label leq + end; + + + + + function ">"(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 323 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 324 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 325 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 326 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 327 + constant length: INTEGER := L'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 328 + constant length: INTEGER := R'length + 1; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 329 + constant length: INTEGER := L'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + function ">"(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to gt + -- synopsys subpgm_id 330 + constant length: INTEGER := R'length; + begin + return is_less(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label gt + end; + + + + + function ">="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 332 + constant length: INTEGER := max(L'length, R'length); + begin + return unsigned_is_less_or_equal(CONV_UNSIGNED(R, length), + CONV_UNSIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 333 + constant length: INTEGER := max(L'length, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 334 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 335 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 336 + constant length: INTEGER := L'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 337 + constant length: INTEGER := R'length + 1; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 338 + constant length: INTEGER := L'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + function ">="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- pragma label_applies_to geq + -- synopsys subpgm_id 339 + constant length: INTEGER := R'length; + begin + return is_less_or_equal(CONV_SIGNED(R, length), + CONV_SIGNED(L, length)); -- pragma label geq + end; + + + + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_eql(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_EQL + begin + for i in L'range loop + if L(i) /= R(i) then + return FALSE; + end if; + end loop; + return TRUE; + end; + + -- for internal use only. Assumes SIGNED arguments of equal length. + function bitwise_neq(L: STD_ULOGIC_VECTOR; R: STD_ULOGIC_VECTOR) + return BOOLEAN is + -- pragma built_in SYN_NEQ + begin + for i in L'range loop + if L(i) /= R(i) then + return TRUE; + end if; + end loop; + return FALSE; + end; + + + function "="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 341 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 342 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 343 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 344 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 345 + constant length: INTEGER := L'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 346 + constant length: INTEGER := R'length + 1; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 347 + constant length: INTEGER := L'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 348 + constant length: INTEGER := R'length; + begin + return bitwise_eql( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + + function "/="(L: UNSIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 350 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_UNSIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_UNSIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 351 + constant length: INTEGER := max(L'length, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 352 + constant length: INTEGER := max(L'length + 1, R'length); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 353 + constant length: INTEGER := max(L'length, R'length + 1); + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: UNSIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 354 + constant length: INTEGER := L'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: UNSIGNED) return BOOLEAN is + -- synopsys subpgm_id 355 + constant length: INTEGER := R'length + 1; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: SIGNED; R: INTEGER) return BOOLEAN is + -- synopsys subpgm_id 356 + constant length: INTEGER := L'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + function "/="(L: INTEGER; R: SIGNED) return BOOLEAN is + -- synopsys subpgm_id 357 + constant length: INTEGER := R'length; + begin + return bitwise_neq( STD_ULOGIC_VECTOR( CONV_SIGNED(L, length) ), + STD_ULOGIC_VECTOR( CONV_SIGNED(R, length) ) ); + end; + + + + function SHL(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 358 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHL(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + -- synopsys subpgm_id 359 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb downto 2**i) := + result(result_msb - 2**i downto 0); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + function SHR(ARG: UNSIGNED; COUNT: UNSIGNED) return UNSIGNED is + -- synopsys subpgm_id 360 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is UNSIGNED (result_msb downto 0); + variable result, temp: rtype; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => '0'); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + function SHR(ARG: SIGNED; COUNT: UNSIGNED) return SIGNED is + -- synopsys subpgm_id 361 + constant control_msb: INTEGER := COUNT'length - 1; + variable control: UNSIGNED (control_msb downto 0); + constant result_msb: INTEGER := ARG'length-1; + subtype rtype is SIGNED (result_msb downto 0); + variable result, temp: rtype; + variable sign_bit: STD_ULOGIC; + begin + control := MAKE_BINARY(COUNT); + -- synopsys synthesis_off + if (control(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + -- synopsys synthesis_on + result := ARG; + sign_bit := ARG(ARG'left); + for i in 0 to control_msb loop + if control(i) = '1' then + temp := rtype'(others => sign_bit); + if 2**i <= result_msb then + temp(result_msb - 2**i downto 0) := + result(result_msb downto 2**i); + end if; + result := temp; + end if; + end loop; + return result; + end; + + + + + function CONV_INTEGER(ARG: INTEGER) return INTEGER is + -- synopsys subpgm_id 365 + begin + return ARG; + end; + + function CONV_INTEGER(ARG: UNSIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_UNSIGNED_TO_INTEGER + -- synopsys subpgm_id 366 + begin + -- synopsys synthesis_off + assert ARG'length <= 31 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: SIGNED) return INTEGER is + variable result: INTEGER; + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_SIGNED_TO_INTEGER + -- synopsys subpgm_id 367 + begin + -- synopsys synthesis_off + assert ARG'length <= 32 + report "ARG is too large in CONV_INTEGER" + severity FAILURE; + result := 0; + for i in ARG'range loop + if i /= ARG'left then + result := result * 2; + tmp := tbl_BINARY(ARG(i)); + if tmp = '1' then + result := result + 1; + elsif tmp = 'X' then + assert false + report "There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)." + severity warning; + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + end if; + end if; + end loop; + tmp := MAKE_BINARY(ARG(ARG'left)); + if tmp = '1' then + if ARG'length = 32 then + result := (result - 2**30) - 2**30; + else + result := result - (2 ** (ARG'length-1)); + end if; + end if; + return result; + -- synopsys synthesis_on + end; + + + function CONV_INTEGER(ARG: STD_ULOGIC) return SMALL_INT is + variable tmp: STD_ULOGIC; + -- synopsys built_in SYN_FEED_THRU + -- synopsys subpgm_id 370 + begin + -- synopsys synthesis_off + tmp := tbl_BINARY(ARG); + if tmp = '1' then + return 1; + elsif tmp = 'X' then + assert false + report "CONV_INTEGER: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, and it has been converted to 0." + severity WARNING; + return 0; + else + return 0; + end if; + -- synopsys synthesis_on + end; + + + -- convert an integer to a unsigned STD_ULOGIC_VECTOR + function CONV_UNSIGNED(ARG: INTEGER; SIZE: INTEGER) return UNSIGNED is + variable result: UNSIGNED(SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_UNSIGNED + -- synopsys subpgm_id 371 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + else + temp := (temp - 1) / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: UNSIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 372 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: SIGNED; SIZE: INTEGER) return UNSIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable new_bounds: UNSIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 373 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_UNSIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return UNSIGNED is + subtype rtype is UNSIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 375 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to a 2's complement STD_ULOGIC_VECTOR + function CONV_SIGNED(ARG: INTEGER; SIZE: INTEGER) return SIGNED is + variable result: SIGNED (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + -- synopsys subpgm_id 376 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + elsif (temp > integer'low) then + temp := (temp - 1) / 2; -- simulate ASR + else + temp := temp / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: UNSIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 377 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_SIGNED(ARG: SIGNED; SIZE: INTEGER) return SIGNED is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is SIGNED (SIZE-1 downto 0); + variable new_bounds : SIGNED (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 378 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_SIGNED(ARG: STD_ULOGIC; SIZE: INTEGER) return SIGNED is + subtype rtype is SIGNED (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 380 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + + -- convert an integer to an STD_LOGIC_VECTOR + function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + variable result: STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable temp: integer; + -- synopsys built_in SYN_INTEGER_TO_SIGNED + -- synopsys subpgm_id 381 + begin + -- synopsys synthesis_off + temp := ARG; + for i in 0 to SIZE-1 loop + if (temp mod 2) = 1 then + result(i) := '1'; + else + result(i) := '0'; + end if; + if temp > 0 then + temp := temp / 2; + elsif (temp > integer'low) then + temp := (temp - 1) / 2; -- simulate ASR + else + temp := temp / 2; -- simulate ASR + end if; + end loop; + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: UNSIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 382 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + function CONV_STD_LOGIC_VECTOR(ARG: SIGNED; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 383 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function CONV_STD_LOGIC_VECTOR(ARG: STD_ULOGIC; SIZE: INTEGER) return STD_LOGIC_VECTOR is + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 384 + begin + -- synopsys synthesis_off + result := rtype'(others => '0'); + result(0) := MAKE_BINARY(ARG); + if (result(0) = 'X') then + result := rtype'(others => 'X'); + end if; + return result; + -- synopsys synthesis_on + end; + + function EXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) + return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds: STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_ZERO_EXTEND + -- synopsys subpgm_id 385 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => '0'); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + + function SXT(ARG: STD_LOGIC_VECTOR; SIZE: INTEGER) return STD_LOGIC_VECTOR is + constant msb: INTEGER := min(ARG'length, SIZE) - 1; + subtype rtype is STD_LOGIC_VECTOR (SIZE-1 downto 0); + variable new_bounds : STD_LOGIC_VECTOR (ARG'length-1 downto 0); + variable result: rtype; + -- synopsys built_in SYN_SIGN_EXTEND + -- synopsys subpgm_id 386 + begin + -- synopsys synthesis_off + new_bounds := MAKE_BINARY(ARG); + if (new_bounds(0) = 'X') then + result := rtype'(others => 'X'); + return result; + end if; + result := rtype'(others => new_bounds(new_bounds'left)); + result(msb downto 0) := new_bounds(msb downto 0); + return result; + -- synopsys synthesis_on + end; + + +end std_logic_arith; diff --git a/lib/Standard/synopsys/std_logic_misc.vhd b/lib/Standard/synopsys/std_logic_misc.vhd new file mode 100644 index 0000000..83bb566 --- /dev/null +++ b/lib/Standard/synopsys/std_logic_misc.vhd @@ -0,0 +1,966 @@ +-------------------------------------------------------------------------- +-- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. +-- +-- This source file may be used and distributed without restriction +-- provided that this copyright statement is not removed from the file +-- and that any derivative work contains this copyright notice. +-- +-- Package name: std_logic_misc +-- +-- Purpose: This package defines supplemental types, subtypes, +-- constants, and functions for the Std_logic_1164 Package. +-- +-- Author: GWH +-- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +library SYNOPSYS; +use SYNOPSYS.attributes.all; + + +package std_logic_misc is + + -- output-strength types + + type STRENGTH is (strn_X01, strn_X0H, strn_XL1, strn_X0Z, strn_XZ1, + strn_WLH, strn_WLZ, strn_WZH, strn_W0H, strn_WL1); + + +--synopsys synthesis_off + + type MINOMAX is array (1 to 3) of TIME; + + + --------------------------------------------------------------------- + -- + -- functions for mapping the STD_(U)LOGIC according to STRENGTH + -- + --------------------------------------------------------------------- + + function strength_map(input: STD_ULOGIC; strn: STRENGTH) return STD_LOGIC; + + function strength_map_z(input:STD_ULOGIC; strn:STRENGTH) return STD_LOGIC; + + --------------------------------------------------------------------- + -- + -- conversion functions for STD_ULOGIC_VECTOR and STD_LOGIC_VECTOR + -- + --------------------------------------------------------------------- + +--synopsys synthesis_on + function Drive (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function Drive (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR; +--synopsys synthesis_off + + attribute CLOSELY_RELATED_TCF of Drive: function is TRUE; + + --------------------------------------------------------------------- + -- + -- conversion functions for sensing various types + -- (the second argument allows the user to specify the value to + -- be returned when the network is undriven) + -- + --------------------------------------------------------------------- + + function Sense (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) return STD_LOGIC; + + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC_VECTOR; + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC_VECTOR; + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR; + +--synopsys synthesis_on + + + --------------------------------------------------------------------- + -- + -- Function: STD_LOGIC_VECTORtoBIT_VECTOR STD_ULOGIC_VECTORtoBIT_VECTOR + -- + -- Purpose: Conversion fun. from STD_(U)LOGIC_VECTOR to BIT_VECTOR + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + + function STD_LOGIC_VECTORtoBIT_VECTOR (V: STD_LOGIC_VECTOR +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT_VECTOR; + + function STD_ULOGIC_VECTORtoBIT_VECTOR (V: STD_ULOGIC_VECTOR +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT_VECTOR; + + + --------------------------------------------------------------------- + -- + -- Function: STD_ULOGICtoBIT + -- + -- Purpose: Conversion function from STD_(U)LOGIC to BIT + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + + function STD_ULOGICtoBIT (V: STD_ULOGIC +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT; + + -------------------------------------------------------------------- + function AND_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function NAND_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function OR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function NOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + function XNOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01; + + function AND_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function NAND_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function OR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function NOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function XOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + function XNOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01; + +--synopsys synthesis_off + + function fun_BUF3S(Input, Enable: UX01; Strn: STRENGTH) return STD_LOGIC; + function fun_BUF3SL(Input, Enable: UX01; Strn: STRENGTH) return STD_LOGIC; + function fun_MUX2x1(Input0, Input1, Sel: UX01) return UX01; + + function fun_MAJ23(Input0, Input1, Input2: UX01) return UX01; + function fun_WiredX(Input0, Input1: std_ulogic) return STD_LOGIC; + +--synopsys synthesis_on + +end; + + +package body std_logic_misc is + +--synopsys synthesis_off + + type STRN_STD_ULOGIC_TABLE is array (STD_ULOGIC,STRENGTH) of STD_ULOGIC; + + -------------------------------------------------------------------- + -- + -- Truth tables for output strength --> STD_ULOGIC lookup + -- + -------------------------------------------------------------------- + + -- truth table for output strength --> STD_ULOGIC lookup + constant tbl_STRN_STD_ULOGIC: STRN_STD_ULOGIC_TABLE := + -- ------------------------------------------------------------------ + -- | X01 X0H XL1 X0Z XZ1 WLH WLZ WZH W0H WL1 | strn/ output| + -- ------------------------------------------------------------------ + (('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'), -- | U | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | X | + ('0', '0', 'L', '0', 'Z', 'L', 'L', 'Z', '0', 'L'), -- | 0 | + ('1', 'H', '1', 'Z', '1', 'H', 'Z', 'H', 'H', '1'), -- | 1 | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | Z | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | W | + ('0', '0', 'L', '0', 'Z', 'L', 'L', 'Z', '0', 'L'), -- | L | + ('1', 'H', '1', 'Z', '1', 'H', 'Z', 'H', 'H', '1'), -- | H | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W')); -- | - | + + + + -------------------------------------------------------------------- + -- + -- Truth tables for strength --> STD_ULOGIC mapping ('Z' pass through) + -- + -------------------------------------------------------------------- + + -- truth table for output strength --> STD_ULOGIC lookup + constant tbl_STRN_STD_ULOGIC_Z: STRN_STD_ULOGIC_TABLE := + -- ------------------------------------------------------------------ + -- | X01 X0H XL1 X0Z XZ1 WLH WLZ WZH W0H WL1 | strn/ output| + -- ------------------------------------------------------------------ + (('U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U'), -- | U | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | X | + ('0', '0', 'L', '0', 'Z', 'L', 'L', 'Z', '0', 'L'), -- | 0 | + ('1', 'H', '1', 'Z', '1', 'H', 'Z', 'H', 'H', '1'), -- | 1 | + ('Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z', 'Z'), -- | Z | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W'), -- | W | + ('0', '0', 'L', '0', 'Z', 'L', 'L', 'Z', '0', 'L'), -- | L | + ('1', 'H', '1', 'Z', '1', 'H', 'Z', 'H', 'H', '1'), -- | H | + ('X', 'X', 'X', 'X', 'X', 'W', 'W', 'W', 'W', 'W')); -- | - | + + + + --------------------------------------------------------------------- + -- + -- functions for mapping the STD_(U)LOGIC according to STRENGTH + -- + --------------------------------------------------------------------- + + function strength_map(input: STD_ULOGIC; strn: STRENGTH) return STD_LOGIC is + -- pragma subpgm_id 387 + begin + return tbl_STRN_STD_ULOGIC(input, strn); + end strength_map; + + + function strength_map_z(input:STD_ULOGIC; strn:STRENGTH) return STD_LOGIC is + -- pragma subpgm_id 388 + begin + return tbl_STRN_STD_ULOGIC_Z(input, strn); + end strength_map_z; + + + --------------------------------------------------------------------- + -- + -- conversion functions for STD_LOGIC_VECTOR and STD_ULOGIC_VECTOR + -- + --------------------------------------------------------------------- + +--synopsys synthesis_on + function Drive (V: STD_LOGIC_VECTOR) return STD_ULOGIC_VECTOR is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 389 +--synopsys synthesis_off + alias Value: STD_LOGIC_VECTOR (V'length-1 downto 0) is V; +--synopsys synthesis_on + begin +--synopsys synthesis_off + return STD_ULOGIC_VECTOR(Value); +--synopsys synthesis_on + end Drive; + + + function Drive (V: STD_ULOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 390 +--synopsys synthesis_off + alias Value: STD_ULOGIC_VECTOR (V'length-1 downto 0) is V; +--synopsys synthesis_on + begin +--synopsys synthesis_off + return STD_LOGIC_VECTOR(Value); +--synopsys synthesis_on + end Drive; +--synopsys synthesis_off + + + --------------------------------------------------------------------- + -- + -- conversion functions for sensing various types + -- + -- (the second argument allows the user to specify the value to + -- be returned when the network is undriven) + -- + --------------------------------------------------------------------- + + function Sense (V: STD_ULOGIC; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC is + -- pragma subpgm_id 391 + begin + if V = 'Z' then + return vZ; + elsif V = 'U' then + return vU; + elsif V = '-' then + return vDC; + else + return V; + end if; + end Sense; + + + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC_VECTOR is + -- pragma subpgm_id 392 + alias Value: STD_ULOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: STD_LOGIC_VECTOR (V'length-1 downto 0); + begin + for i in Value'range loop + if ( Value(i) = 'Z' ) then + Result(i) := vZ; + elsif Value(i) = 'U' then + Result(i) := vU; + elsif Value(i) = '-' then + Result(i) := vDC; + else + Result(i) := Value(i); + end if; + end loop; + return Result; + end Sense; + + + function Sense (V: STD_ULOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR is + -- pragma subpgm_id 393 + alias Value: STD_ULOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: STD_ULOGIC_VECTOR (V'length-1 downto 0); + begin + for i in Value'range loop + if ( Value(i) = 'Z' ) then + Result(i) := vZ; + elsif Value(i) = 'U' then + Result(i) := vU; + elsif Value(i) = '-' then + Result(i) := vDC; + else + Result(i) := Value(i); + end if; + end loop; + return Result; + end Sense; + + + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_LOGIC_VECTOR is + -- pragma subpgm_id 394 + alias Value: STD_LOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: STD_LOGIC_VECTOR (V'length-1 downto 0); + begin + for i in Value'range loop + if ( Value(i) = 'Z' ) then + Result(i) := vZ; + elsif Value(i) = 'U' then + Result(i) := vU; + elsif Value(i) = '-' then + Result(i) := vDC; + else + Result(i) := Value(i); + end if; + end loop; + return Result; + end Sense; + + + function Sense (V: STD_LOGIC_VECTOR; vZ, vU, vDC: STD_ULOGIC) + return STD_ULOGIC_VECTOR is + -- pragma subpgm_id 395 + alias Value: STD_LOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: STD_ULOGIC_VECTOR (V'length-1 downto 0); + begin + for i in Value'range loop + if ( Value(i) = 'Z' ) then + Result(i) := vZ; + elsif Value(i) = 'U' then + Result(i) := vU; + elsif Value(i) = '-' then + Result(i) := vDC; + else + Result(i) := Value(i); + end if; + end loop; + return Result; + end Sense; + + --------------------------------------------------------------------- + -- + -- Function: STD_LOGIC_VECTORtoBIT_VECTOR + -- + -- Purpose: Conversion fun. from STD_LOGIC_VECTOR to BIT_VECTOR + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + +--synopsys synthesis_on + function STD_LOGIC_VECTORtoBIT_VECTOR (V: STD_LOGIC_VECTOR +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT_VECTOR is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 396 +--synopsys synthesis_off + alias Value: STD_LOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: BIT_VECTOR (V'length-1 downto 0); +--synopsys synthesis_on + begin +--synopsys synthesis_off + for i in Value'range loop + case Value(i) is + when '0' | 'L' => + Result(i) := '0'; + when '1' | 'H' => + Result(i) := '1'; + when 'X' => + if ( Xflag ) then + Result(i) := vX; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: X --> 0" + severity WARNING; + end if; + when 'W' => + if ( Xflag ) then + Result(i) := vX; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: W --> 0" + severity WARNING; + end if; + when 'Z' => + if ( Zflag ) then + Result(i) := vZ; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: Z --> 0" + severity WARNING; + end if; + when 'U' => + if ( Uflag ) then + Result(i) := vU; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: U --> 0" + severity WARNING; + end if; + when '-' => + if ( DCflag ) then + Result(i) := vDC; + else + Result(i) := '0'; + assert FALSE + report "STD_LOGIC_VECTORtoBIT_VECTOR: - --> 0" + severity WARNING; + end if; + end case; + end loop; + return Result; +--synopsys synthesis_on + end STD_LOGIC_VECTORtoBIT_VECTOR; + + + + + --------------------------------------------------------------------- + -- + -- Function: STD_ULOGIC_VECTORtoBIT_VECTOR + -- + -- Purpose: Conversion fun. from STD_ULOGIC_VECTOR to BIT_VECTOR + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + + function STD_ULOGIC_VECTORtoBIT_VECTOR (V: STD_ULOGIC_VECTOR +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT_VECTOR is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 397 +--synopsys synthesis_off + alias Value: STD_ULOGIC_VECTOR (V'length-1 downto 0) is V; + variable Result: BIT_VECTOR (V'length-1 downto 0); +--synopsys synthesis_on + begin +--synopsys synthesis_off + for i in Value'range loop + case Value(i) is + when '0' | 'L' => + Result(i) := '0'; + when '1' | 'H' => + Result(i) := '1'; + when 'X' => + if ( Xflag ) then + Result(i) := vX; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: X --> 0" + severity WARNING; + end if; + when 'W' => + if ( Xflag ) then + Result(i) := vX; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: W --> 0" + severity WARNING; + end if; + when 'Z' => + if ( Zflag ) then + Result(i) := vZ; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: Z --> 0" + severity WARNING; + end if; + when 'U' => + if ( Uflag ) then + Result(i) := vU; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: U --> 0" + severity WARNING; + end if; + when '-' => + if ( DCflag ) then + Result(i) := vDC; + else + Result(i) := '0'; + assert FALSE + report "STD_ULOGIC_VECTORtoBIT_VECTOR: - --> 0" + severity WARNING; + end if; + end case; + end loop; + return Result; +--synopsys synthesis_on + end STD_ULOGIC_VECTORtoBIT_VECTOR; + + + + + --------------------------------------------------------------------- + -- + -- Function: STD_ULOGICtoBIT + -- + -- Purpose: Conversion function from STD_ULOGIC to BIT + -- + -- Mapping: 0, L --> 0 + -- 1, H --> 1 + -- X, W --> vX if Xflag is TRUE + -- X, W --> 0 if Xflag is FALSE + -- Z --> vZ if Zflag is TRUE + -- Z --> 0 if Zflag is FALSE + -- U --> vU if Uflag is TRUE + -- U --> 0 if Uflag is FALSE + -- - --> vDC if DCflag is TRUE + -- - --> 0 if DCflag is FALSE + -- + --------------------------------------------------------------------- + + function STD_ULOGICtoBIT (V: STD_ULOGIC +--synopsys synthesis_off + ; vX, vZ, vU, vDC: BIT := '0'; + Xflag, Zflag, Uflag, DCflag: BOOLEAN := FALSE +--synopsys synthesis_on + ) return BIT is + -- pragma built_in SYN_FEED_THRU + -- pragma subpgm_id 398 + variable Result: BIT; + begin +--synopsys synthesis_off + case V is + when '0' | 'L' => + Result := '0'; + when '1' | 'H' => + Result := '1'; + when 'X' => + if ( Xflag ) then + Result := vX; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: X --> 0" + severity WARNING; + end if; + when 'W' => + if ( Xflag ) then + Result := vX; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: W --> 0" + severity WARNING; + end if; + when 'Z' => + if ( Zflag ) then + Result := vZ; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: Z --> 0" + severity WARNING; + end if; + when 'U' => + if ( Uflag ) then + Result := vU; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: U --> 0" + severity WARNING; + end if; + when '-' => + if ( DCflag ) then + Result := vDC; + else + Result := '0'; + assert FALSE + report "STD_ULOGICtoBIT: - --> 0" + severity WARNING; + end if; + end case; + return Result; +--synopsys synthesis_on + end STD_ULOGICtoBIT; + + + -------------------------------------------------------------------------- + + function AND_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 399 + variable result: STD_LOGIC; + begin + result := '1'; + for i in ARG'range loop + result := result and ARG(i); + end loop; + return result; + end; + + function NAND_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 400 + begin + return not AND_REDUCE(ARG); + end; + + function OR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 401 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result or ARG(i); + end loop; + return result; + end; + + function NOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 402 + begin + return not OR_REDUCE(ARG); + end; + + function XOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 403 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + + function XNOR_REDUCE(ARG: STD_LOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 404 + begin + return not XOR_REDUCE(ARG); + end; + + function AND_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 405 + variable result: STD_LOGIC; + begin + result := '1'; + for i in ARG'range loop + result := result and ARG(i); + end loop; + return result; + end; + + function NAND_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 406 + begin + return not AND_REDUCE(ARG); + end; + + function OR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 407 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result or ARG(i); + end loop; + return result; + end; + + function NOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 408 + begin + return not OR_REDUCE(ARG); + end; + + function XOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 409 + variable result: STD_LOGIC; + begin + result := '0'; + for i in ARG'range loop + result := result xor ARG(i); + end loop; + return result; + end; + + function XNOR_REDUCE(ARG: STD_ULOGIC_VECTOR) return UX01 is + -- pragma subpgm_id 410 + begin + return not XOR_REDUCE(ARG); + end; + +--synopsys synthesis_off + + function fun_BUF3S(Input, Enable: UX01; Strn: STRENGTH) return STD_LOGIC is + -- pragma subpgm_id 411 + type TRISTATE_TABLE is array(STRENGTH, UX01, UX01) of STD_LOGIC; + + -- truth table for tristate "buf" function (Enable active Low) + constant tbl_BUF3S: TRISTATE_TABLE := + -- ---------------------------------------------------- + -- | Input U X 0 1 | Enable Strength | + -- ---------------------------------|-----------------| + ((('U', 'U', 'U', 'U'), --| U X01 | + ('U', 'X', 'X', 'X'), --| X X01 | + ('Z', 'Z', 'Z', 'Z'), --| 0 X01 | + ('U', 'X', '0', '1')), --| 1 X01 | + (('U', 'U', 'U', 'U'), --| U X0H | + ('U', 'X', 'X', 'X'), --| X X0H | + ('Z', 'Z', 'Z', 'Z'), --| 0 X0H | + ('U', 'X', '0', 'H')), --| 1 X0H | + (('U', 'U', 'U', 'U'), --| U XL1 | + ('U', 'X', 'X', 'X'), --| X XL1 | + ('Z', 'Z', 'Z', 'Z'), --| 0 XL1 | + ('U', 'X', 'L', '1')), --| 1 XL1 | + (('U', 'U', 'U', 'Z'), --| U X0Z | + ('U', 'X', 'X', 'Z'), --| X X0Z | + ('Z', 'Z', 'Z', 'Z'), --| 0 X0Z | + ('U', 'X', '0', 'Z')), --| 1 X0Z | + (('U', 'U', 'U', 'U'), --| U XZ1 | + ('U', 'X', 'X', 'X'), --| X XZ1 | + ('Z', 'Z', 'Z', 'Z'), --| 0 XZ1 | + ('U', 'X', 'Z', '1')), --| 1 XZ1 | + (('U', 'U', 'U', 'U'), --| U WLH | + ('U', 'W', 'W', 'W'), --| X WLH | + ('Z', 'Z', 'Z', 'Z'), --| 0 WLH | + ('U', 'W', 'L', 'H')), --| 1 WLH | + (('U', 'U', 'U', 'U'), --| U WLZ | + ('U', 'W', 'W', 'Z'), --| X WLZ | + ('Z', 'Z', 'Z', 'Z'), --| 0 WLZ | + ('U', 'W', 'L', 'Z')), --| 1 WLZ | + (('U', 'U', 'U', 'U'), --| U WZH | + ('U', 'W', 'W', 'W'), --| X WZH | + ('Z', 'Z', 'Z', 'Z'), --| 0 WZH | + ('U', 'W', 'Z', 'H')), --| 1 WZH | + (('U', 'U', 'U', 'U'), --| U W0H | + ('U', 'W', 'W', 'W'), --| X W0H | + ('Z', 'Z', 'Z', 'Z'), --| 0 W0H | + ('U', 'W', '0', 'H')), --| 1 W0H | + (('U', 'U', 'U', 'U'), --| U WL1 | + ('U', 'W', 'W', 'W'), --| X WL1 | + ('Z', 'Z', 'Z', 'Z'), --| 0 WL1 | + ('U', 'W', 'L', '1')));--| 1 WL1 | + begin + return tbl_BUF3S(Strn, Enable, Input); + end fun_BUF3S; + + + function fun_BUF3SL(Input, Enable: UX01; Strn: STRENGTH) return STD_LOGIC is + -- pragma subpgm_id 412 + type TRISTATE_TABLE is array(STRENGTH, UX01, UX01) of STD_LOGIC; + + -- truth table for tristate "buf" function (Enable active Low) + constant tbl_BUF3SL: TRISTATE_TABLE := + -- ---------------------------------------------------- + -- | Input U X 0 1 | Enable Strength | + -- ---------------------------------|-----------------| + ((('U', 'U', 'U', 'U'), --| U X01 | + ('U', 'X', 'X', 'X'), --| X X01 | + ('U', 'X', '0', '1'), --| 0 X01 | + ('Z', 'Z', 'Z', 'Z')), --| 1 X01 | + (('U', 'U', 'U', 'U'), --| U X0H | + ('U', 'X', 'X', 'X'), --| X X0H | + ('U', 'X', '0', 'H'), --| 0 X0H | + ('Z', 'Z', 'Z', 'Z')), --| 1 X0H | + (('U', 'U', 'U', 'U'), --| U XL1 | + ('U', 'X', 'X', 'X'), --| X XL1 | + ('U', 'X', 'L', '1'), --| 0 XL1 | + ('Z', 'Z', 'Z', 'Z')), --| 1 XL1 | + (('U', 'U', 'U', 'Z'), --| U X0Z | + ('U', 'X', 'X', 'Z'), --| X X0Z | + ('U', 'X', '0', 'Z'), --| 0 X0Z | + ('Z', 'Z', 'Z', 'Z')), --| 1 X0Z | + (('U', 'U', 'U', 'U'), --| U XZ1 | + ('U', 'X', 'X', 'X'), --| X XZ1 | + ('U', 'X', 'Z', '1'), --| 0 XZ1 | + ('Z', 'Z', 'Z', 'Z')), --| 1 XZ1 | + (('U', 'U', 'U', 'U'), --| U WLH | + ('U', 'W', 'W', 'W'), --| X WLH | + ('U', 'W', 'L', 'H'), --| 0 WLH | + ('Z', 'Z', 'Z', 'Z')), --| 1 WLH | + (('U', 'U', 'U', 'U'), --| U WLZ | + ('U', 'W', 'W', 'Z'), --| X WLZ | + ('U', 'W', 'L', 'Z'), --| 0 WLZ | + ('Z', 'Z', 'Z', 'Z')), --| 1 WLZ | + (('U', 'U', 'U', 'U'), --| U WZH | + ('U', 'W', 'W', 'W'), --| X WZH | + ('U', 'W', 'Z', 'H'), --| 0 WZH | + ('Z', 'Z', 'Z', 'Z')), --| 1 WZH | + (('U', 'U', 'U', 'U'), --| U W0H | + ('U', 'W', 'W', 'W'), --| X W0H | + ('U', 'W', '0', 'H'), --| 0 W0H | + ('Z', 'Z', 'Z', 'Z')), --| 1 W0H | + (('U', 'U', 'U', 'U'), --| U WL1 | + ('U', 'W', 'W', 'W'), --| X WL1 | + ('U', 'W', 'L', '1'), --| 0 WL1 | + ('Z', 'Z', 'Z', 'Z')));--| 1 WL1 | + begin + return tbl_BUF3SL(Strn, Enable, Input); + end fun_BUF3SL; + + + function fun_MUX2x1(Input0, Input1, Sel: UX01) return UX01 is + -- pragma subpgm_id 413 + type MUX_TABLE is array (UX01, UX01, UX01) of UX01; + + -- truth table for "MUX2x1" function + constant tbl_MUX2x1: MUX_TABLE := + -------------------------------------------- + --| In0 'U' 'X' '0' '1' | Sel In1 | + -------------------------------------------- + ((('U', 'U', 'U', 'U'), --| 'U' 'U' | + ('U', 'U', 'U', 'U'), --| 'X' 'U' | + ('U', 'X', '0', '1'), --| '0' 'U' | + ('U', 'U', 'U', 'U')), --| '1' 'U' | + (('U', 'X', 'U', 'U'), --| 'U' 'X' | + ('U', 'X', 'X', 'X'), --| 'X' 'X' | + ('U', 'X', '0', '1'), --| '0' 'X' | + ('X', 'X', 'X', 'X')), --| '1' 'X' | + (('U', 'U', '0', 'U'), --| 'U' '0' | + ('U', 'X', '0', 'X'), --| 'X' '0' | + ('U', 'X', '0', '1'), --| '0' '0' | + ('0', '0', '0', '0')), --| '1' '0' | + (('U', 'U', 'U', '1'), --| 'U' '1' | + ('U', 'X', 'X', '1'), --| 'X' '1' | + ('U', 'X', '0', '1'), --| '0' '1' | + ('1', '1', '1', '1')));--| '1' '1' | + begin + return tbl_MUX2x1(Input1, Sel, Input0); + end fun_MUX2x1; + + + function fun_MAJ23(Input0, Input1, Input2: UX01) return UX01 is + -- pragma subpgm_id 414 + type MAJ23_TABLE is array (UX01, UX01, UX01) of UX01; + + ---------------------------------------------------------------------------- + -- The "tbl_MAJ23" truth table return 1 if the majority of three + -- inputs is 1, a 0 if the majority is 0, a X if unknown, and a U if + -- uninitialized. + ---------------------------------------------------------------------------- + constant tbl_MAJ23: MAJ23_TABLE := + -------------------------------------------- + --| In0 'U' 'X' '0' '1' | In1 In2 | + -------------------------------------------- + ((('U', 'U', 'U', 'U'), --| 'U' 'U' | + ('U', 'U', 'U', 'U'), --| 'X' 'U' | + ('U', 'U', '0', 'U'), --| '0' 'U' | + ('U', 'U', 'U', '1')), --| '1' 'U' | + (('U', 'U', 'U', 'U'), --| 'U' 'X' | + ('U', 'X', 'X', 'X'), --| 'X' 'X' | + ('U', 'X', '0', 'X'), --| '0' 'X' | + ('U', 'X', 'X', '1')), --| '1' 'X' | + (('U', 'U', '0', 'U'), --| 'U' '0' | + ('U', 'X', '0', 'X'), --| 'X' '0' | + ('0', '0', '0', '0'), --| '0' '0' | + ('U', 'X', '0', '1')), --| '1' '0' | + (('U', 'U', 'U', '1'), --| 'U' '1' | + ('U', 'X', 'X', '1'), --| 'X' '1' | + ('U', 'X', '0', '1'), --| '0' '1' | + ('1', '1', '1', '1')));--| '1' '1' | + + begin + return tbl_MAJ23(Input0, Input1, Input2); + end fun_MAJ23; + + + function fun_WiredX(Input0, Input1: STD_ULOGIC) return STD_LOGIC is + -- pragma subpgm_id 415 + TYPE stdlogic_table IS ARRAY(STD_ULOGIC, STD_ULOGIC) OF STD_LOGIC; + + -- truth table for "WiredX" function + ------------------------------------------------------------------- + -- resolution function + ------------------------------------------------------------------- + CONSTANT resolution_table : stdlogic_table := ( + -- --------------------------------------------------------- + -- | U X 0 1 Z W L H - | | + -- --------------------------------------------------------- + ( 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U', 'U' ), -- | U | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ), -- | X | + ( 'U', 'X', '0', 'X', '0', '0', '0', '0', 'X' ), -- | 0 | + ( 'U', 'X', 'X', '1', '1', '1', '1', '1', 'X' ), -- | 1 | + ( 'U', 'X', '0', '1', 'Z', 'W', 'L', 'H', 'X' ), -- | Z | + ( 'U', 'X', '0', '1', 'W', 'W', 'W', 'W', 'X' ), -- | W | + ( 'U', 'X', '0', '1', 'L', 'W', 'L', 'W', 'X' ), -- | L | + ( 'U', 'X', '0', '1', 'H', 'W', 'W', 'H', 'X' ), -- | H | + ( 'U', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' ));-- | - | + begin + return resolution_table(Input0, Input1); + end fun_WiredX; + +--synopsys synthesis_on + +end; diff --git a/lib/Standard/synopsys/std_logic_signed.vhd b/lib/Standard/synopsys/std_logic_signed.vhd new file mode 100644 index 0000000..27d211b --- /dev/null +++ b/lib/Standard/synopsys/std_logic_signed.vhd @@ -0,0 +1,343 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_SIGNED -- +-- -- +-- -- +-- Date: 09/11/91 KN -- +-- 10/08/92 AMT change std_ulogic to signed std_logic -- +-- 10/28/92 AMT added signed functions, -, ABS -- +-- -- +-- Purpose: -- +-- A set of signed arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: Comparision of same length std_logic_vector is defined -- +-- in the LRM. The interpretation is for unsigned vectors -- +-- This package will "overload" that definition. -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_SIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "ABS"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_SIGNED; + + + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package body STD_LOGIC_SIGNED is + + + function maximum(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := SIGNED(L) + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) + R; -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) + R; -- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + SIGNED(R); -- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := SIGNED(L) - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := SIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - SIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := + SIGNED(L); -- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := - SIGNED(L); -- pragma label minus + return std_logic_vector(result); + end; + + function "ABS"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := ABS( SIGNED(L)); + return std_logic_vector(result); + end; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR ((L'length+R'length-1) downto 0); + begin + result := SIGNED(L) * SIGNED(R); -- pragma label mult + return std_logic_vector(result); + end; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := maximum(L'length, R'length); + begin + return SIGNED(L) < SIGNED(R); -- pragma label lt + end; + + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + begin + return SIGNED(L) < R; -- pragma label lt + end; + + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + begin + return L < SIGNED(R); -- pragma label lt + end; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return SIGNED(L) <= SIGNED(R); -- pragma label leq + end; + + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + begin + return SIGNED(L) <= R; -- pragma label leq + end; + + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return L <= SIGNED(R); -- pragma label leq + end; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return SIGNED(L) > SIGNED(R); -- pragma label gt + end; + + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + begin + return SIGNED(L) > R; -- pragma label gt + end; + + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return L > SIGNED(R); -- pragma label gt + end; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return SIGNED(L) >= SIGNED(R); -- pragma label geq + end; + + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + begin + return SIGNED(L) >= R; -- pragma label geq + end; + + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return L >= SIGNED(R); -- pragma label geq + end; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return SIGNED(L) = SIGNED(R); + end; + + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return SIGNED(L) = R; + end; + + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L = SIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return SIGNED(L) /= SIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return SIGNED(L) /= R; + end; + + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L /= SIGNED(R); + end; + + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHL(SIGNED(ARG),UNSIGNED(COUNT))); + end; + + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHR(SIGNED(ARG),UNSIGNED(COUNT))); + end; + + + +-- This function converts std_logic_vector to a signed integer value +-- using a conversion function in std_logic_arith + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER is + variable result : SIGNED(ARG'range); + begin + result := SIGNED(ARG); + return CONV_INTEGER(result); + end; +end STD_LOGIC_SIGNED; + + diff --git a/lib/Standard/synopsys/std_logic_textio.vhd b/lib/Standard/synopsys/std_logic_textio.vhd new file mode 100644 index 0000000..260c1f3 --- /dev/null +++ b/lib/Standard/synopsys/std_logic_textio.vhd @@ -0,0 +1,654 @@ +---------------------------------------------------------------------------- +-- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. +-- +-- This source file may be used and distributed without restriction +-- provided that this copyright statement is not removed from the file +-- and that any derivative work contains this copyright notice. +-- +-- Package name: STD_LOGIC_TEXTIO +-- +-- Purpose: This package overloads the standard TEXTIO procedures +-- READ and WRITE. +-- +-- Author: CRC, TS +-- +---------------------------------------------------------------------------- + +use STD.textio.all; +library IEEE; +use IEEE.std_logic_1164.all; + +package STD_LOGIC_TEXTIO is +--synopsys synthesis_off + -- Read and Write procedures for STD_ULOGIC and STD_ULOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD: out BOOLEAN); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Read and Write procedures for STD_LOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- + -- Read and Write procedures for Hex and Octal values. + -- The values appear in the file as a series of characters + -- between 0-F (Hex), or 0-7 (Octal) respectively. + -- + + -- Hex + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + -- Octal + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); + procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); + + +--synopsys synthesis_on +end STD_LOGIC_TEXTIO; + +package body STD_LOGIC_TEXTIO is +--synopsys synthesis_off + + -- Type and constant definitions used to map STD_ULOGIC values + -- into/from character values. + + type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', ERROR); + type char_indexed_by_MVL9 is array (STD_ULOGIC) of character; + type MVL9_indexed_by_char is array (character) of STD_ULOGIC; + type MVL9plus_indexed_by_char is array (character) of MVL9plus; + + constant MVL9_to_char: char_indexed_by_MVL9 := "UX01ZWLH-"; + constant char_to_MVL9: MVL9_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); + constant char_to_MVL9plus: MVL9plus_indexed_by_char := + ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', + 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => ERROR); + + + -- Overloaded procedures. + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD:out BOOLEAN) is + variable c: character; + variable readOk: BOOLEAN; + begin + loop -- skip white space + read(l,c,readOk); -- but also exit on a bad read + exit when ((readOk = FALSE) or ((c /= ' ') and (c /= CR) and (c /= HT))); + end loop; + + if (readOk = FALSE) then + good := FALSE; + else + if (char_to_MVL9plus(c) = ERROR) then + value := 'U'; + good := FALSE; + else + value := char_to_MVL9(c); + good := TRUE; + end if; + end if; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD:out BOOLEAN) is + variable m: STD_ULOGIC; + variable c: character; + variable s: string(1 to value'length-1); + variable mv: STD_ULOGIC_VECTOR(0 to value'length-1); + constant allU: STD_ULOGIC_VECTOR(0 to value'length-1) + := (others => 'U'); + variable readOk: BOOLEAN; + + begin + loop -- skip white space + read(l,c,readOk); + exit when ((readOk = FALSE) or ((c /= ' ') and (c /= CR) and (c /= HT))); + end loop; + +-- Bail out if there was a bad read + if (readOk = FALSE) then + good := FALSE; + return; + end if; + + if (char_to_MVL9plus(c) = ERROR) then + value := allU; + good := FALSE; + return; + end if; + + read(l, s, readOk); +-- Bail out if there was a bad read + if (readOk = FALSE) then + good := FALSE; + return; + end if; + + for i in 1 to value'length-1 loop + if (char_to_MVL9plus(s(i)) = ERROR) then + value := allU; + good := FALSE; + return; + end if; + end loop; + + mv(0) := char_to_MVL9(c); + for i in 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := mv; + good := TRUE; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC) is + variable c: character; + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := 'U'; + assert FALSE report "READ(STD_ULOGIC) Error: Character '" & + c & "' read, expected STD_ULOGIC literal."; + else + value := char_to_MVL9(c); + end if; + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable m: STD_ULOGIC; + variable c: character; + variable s: string(1 to value'length-1); + variable mv: STD_ULOGIC_VECTOR(0 to value'length-1); + constant allU: STD_ULOGIC_VECTOR(0 to value'length-1) + := (others => 'U'); + begin + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + if (char_to_MVL9plus(c) = ERROR) then + value := allU; + assert FALSE report + "READ(STD_ULOGIC_VECTOR) Error: Character '" & + c & "' read, expected STD_ULOGIC literal."; + return; + end if; + + read(l, s); + for i in 1 to value'length-1 loop + if (char_to_MVL9plus(s(i)) = ERROR) then + value := allU; + assert FALSE report + "READ(STD_ULOGIC_VECTOR) Error: Character '" & + s(i) & "' read, expected STD_ULOGIC literal."; + return; + end if; + end loop; + + mv(0) := char_to_MVL9(c); + for i in 1 to value'length-1 loop + mv(i) := char_to_MVL9(s(i)); + end loop; + value := mv; + end READ; + + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + write(l, MVL9_to_char(value), justified, field); + end WRITE; + + + procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable s: string(1 to value'length); + variable m: STD_ULOGIC_VECTOR(1 to value'length) := value; + begin + for i in 1 to value'length loop + s(i) := MVL9_to_char(m(i)); + end loop; + write(l, s, justified, field); + end WRITE; + + -- Read and Write procedures for STD_LOGIC_VECTOR + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + READ(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end READ; + + procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + READ(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end READ; + + procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + WRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); + end WRITE; + + + -- + -- Hex Read and Write procedures. + -- + + -- + -- Hex, and Octal Read and Write procedures for BIT_VECTOR + -- (these procedures are not exported, they are only used + -- by the STD_ULOGIC hex/octal reads and writes below. + -- + -- + + procedure Char2QuadBits(C: Character; + RESULT: out std_ulogic_vector(3 downto 0); + GOOD: out Boolean; + ISSUE_ERROR: in Boolean) is + begin + case c is + when '0' => result := x"0"; good := TRUE; + when '1' => result := x"1"; good := TRUE; + when '2' => result := x"2"; good := TRUE; + when '3' => result := x"3"; good := TRUE; + when '4' => result := x"4"; good := TRUE; + when '5' => result := x"5"; good := TRUE; + when '6' => result := x"6"; good := TRUE; + when '7' => result := x"7"; good := TRUE; + when '8' => result := x"8"; good := TRUE; + when '9' => result := x"9"; good := TRUE; + when 'A' => result := x"A"; good := TRUE; + when 'B' => result := x"B"; good := TRUE; + when 'C' => result := x"C"; good := TRUE; + when 'D' => result := x"D"; good := TRUE; + when 'E' => result := x"E"; good := TRUE; + when 'F' => result := x"F"; good := TRUE; + when 'Z' => result(0) := 'Z'; result(1) := 'Z'; result(2) := 'Z'; result(3) := 'Z'; good := TRUE; + when 'X' => result(0) := 'X'; result(1) := 'X'; result(2) := 'X'; result(3) := 'X'; good := TRUE; + + when 'a' => result := x"A"; good := TRUE; + when 'b' => result := x"B"; good := TRUE; + when 'c' => result := x"C"; good := TRUE; + when 'd' => result := x"D"; good := TRUE; + when 'e' => result := x"E"; good := TRUE; + when 'f' => result := x"F"; good := TRUE; + when others => + if ISSUE_ERROR then + assert FALSE report + "HREAD Error: Read a '" & c & + "', expected a Hex character (0-F)."; + end if; + good := FALSE; + end case; + end; + + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/4; + variable bv: std_ulogic_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 4 /= 0 then + assert FALSE report + "HREAD Error: Trying to read vector " & + "with an odd (non multiple of 4) length"; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2QuadBits(c, bv(0 to 3), ok, TRUE); + if not ok then + return; + end if; + + read(L, s, ok); + if not ok then + assert FALSE + report "HREAD Error: Failed to read the STRING"; + return; + end if; + + for i in 1 to ne-1 loop + Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, TRUE); + if not ok then + return; + end if; + end loop; + value := bv; + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD: out BOOLEAN) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/4; + variable bv: std_ulogic_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 4 /= 0 then + good := FALSE; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2QuadBits(c, bv(0 to 3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + + for i in 1 to ne-1 loop + Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + good := TRUE; + value := bv; + end HREAD; + + procedure HWRITE(L:inout LINE; VALUE:in std_ulogic_vector; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable quad: std_ulogic_vector(0 to 3); + constant ne: integer := value'length/4; + variable bv: std_ulogic_vector(0 to value'length-1) := value; + variable s: string(1 to ne); + begin + if value'length mod 4 /= 0 then + assert FALSE report + "HWRITE Error: Trying to read vector " & + "with an odd (non multiple of 4) length"; + return; + end if; + + for i in 0 to ne-1 loop + quad := To_X01Z(bv(4*i to 4*i+3)); + case quad is + when x"0" => s(i+1) := '0'; + when x"1" => s(i+1) := '1'; + when x"2" => s(i+1) := '2'; + when x"3" => s(i+1) := '3'; + when x"4" => s(i+1) := '4'; + when x"5" => s(i+1) := '5'; + when x"6" => s(i+1) := '6'; + when x"7" => s(i+1) := '7'; + when x"8" => s(i+1) := '8'; + when x"9" => s(i+1) := '9'; + when x"A" => s(i+1) := 'A'; + when x"B" => s(i+1) := 'B'; + when x"C" => s(i+1) := 'C'; + when x"D" => s(i+1) := 'D'; + when x"E" => s(i+1) := 'E'; + when x"F" => s(i+1) := 'F'; + when others => + if (quad = "ZZZZ") then + s(i+1) := 'Z'; + else + s(i+1) := 'X'; + end if; + end case; + end loop; + write(L, s, JUSTIFIED, FIELD); + end HWRITE; + + procedure Char2TriBits(C: Character; + RESULT: out bit_vector(2 downto 0); + GOOD: out Boolean; + ISSUE_ERROR: in Boolean) is + begin + case c is + when '0' => result := o"0"; good := TRUE; + when '1' => result := o"1"; good := TRUE; + when '2' => result := o"2"; good := TRUE; + when '3' => result := o"3"; good := TRUE; + when '4' => result := o"4"; good := TRUE; + when '5' => result := o"5"; good := TRUE; + when '6' => result := o"6"; good := TRUE; + when '7' => result := o"7"; good := TRUE; + when others => + if ISSUE_ERROR then + assert FALSE report + "OREAD Error: Read a '" & c & + "', expected an Octal character (0-7)."; + end if; + good := FALSE; + end case; + end; + + procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR) is + variable c: character; + variable ok: boolean; + constant ne: integer := value'length/3; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 3 /= 0 then + assert FALSE report + "OREAD Error: Trying to read vector " & + "with an odd (non multiple of 3) length"; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2TriBits(c, bv(0 to 2), ok, TRUE); + if not ok then + return; + end if; + + read(L, s, ok); + if not ok then + assert FALSE + report "OREAD Error: Failed to read the STRING"; + return; + end if; + + for i in 1 to ne-1 loop + Char2TriBits(s(i), bv(3*i to 3*i+2), ok, TRUE); + if not ok then + return; + end if; + end loop; + value := bv; + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD: out BOOLEAN) is + variable ok: boolean; + variable c: character; + constant ne: integer := value'length/3; + variable bv: bit_vector(0 to value'length-1); + variable s: string(1 to ne-1); + begin + if value'length mod 3 /= 0 then + good := FALSE; + return; + end if; + + loop -- skip white space + read(l,c); + exit when ((c /= ' ') and (c /= CR) and (c /= HT)); + end loop; + + Char2TriBits(c, bv(0 to 2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + + read(L, s, ok); + if not ok then + good := FALSE; + return; + end if; + + for i in 1 to ne-1 loop + Char2TriBits(s(i), bv(3*i to 3*i+2), ok, FALSE); + if not ok then + good := FALSE; + return; + end if; + end loop; + good := TRUE; + value := bv; + end OREAD; + + + procedure OWRITE(L:inout LINE; VALUE:in std_ulogic_vector; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + variable tri: std_ulogic_vector(0 to 2); + constant ne: integer := value'length/3; + variable bv: std_ulogic_vector(0 to value'length-1) := value; + variable s: string(1 to ne); + begin + if value'length mod 3 /= 0 then + assert FALSE report + "OWRITE Error: Trying to read vector " & + "with an odd (non multiple of 3) length"; + return; + end if; + + for i in 0 to ne-1 loop + tri := To_X01Z(bv(3*i to 3*i+2)); + case tri is + when o"0" => s(i+1) := '0'; + when o"1" => s(i+1) := '1'; + when o"2" => s(i+1) := '2'; + when o"3" => s(i+1) := '3'; + when o"4" => s(i+1) := '4'; + when o"5" => s(i+1) := '5'; + when o"6" => s(i+1) := '6'; + when o"7" => s(i+1) := '7'; + when others => + if (tri = "ZZZ") then + s(i+1) := 'Z'; + else + s(i+1) := 'X'; + end if; + end case; + end loop; + write(L, s, JUSTIFIED, FIELD); + end OWRITE; + + -- Hex Read and Write procedures for STD_LOGIC_VECTOR + procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD:out BOOLEAN) is + variable tmp: std_ulogic_vector(VALUE'length-1 downto 0); + begin + HREAD(L, tmp, GOOD); + VALUE := To_BitVector(tmp); + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR) is + variable tmp: std_ulogic_vector(VALUE'length-1 downto 0); + begin + HREAD(L, tmp); + VALUE := To_BitVector(tmp); + end HREAD; + + -- Hex Read and Write procedures for STD_LOGIC_VECTOR + + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + HREAD(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end HREAD; + + procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + HREAD(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end HREAD; + + procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + HWRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); + end HWRITE; + + + -- Octal Read and Write procedures for STD_ULOGIC_VECTOR + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD:out BOOLEAN) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + OREAD(L, tmp, GOOD); + VALUE := To_X01(tmp); + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is + variable tmp: bit_vector(VALUE'length-1 downto 0); + begin + OREAD(L, tmp); + VALUE := To_X01(tmp); + end OREAD; + + -- Octal Read and Write procedures for STD_LOGIC_VECTOR + + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + OREAD(L, tmp); + VALUE := STD_LOGIC_VECTOR(tmp); + end OREAD; + + procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is + variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); + begin + OREAD(L, tmp, GOOD); + VALUE := STD_LOGIC_VECTOR(tmp); + end OREAD; + + procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; + JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is + begin + OWRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); + end OWRITE; + + +--synopsys synthesis_on +end STD_LOGIC_TEXTIO; diff --git a/lib/Standard/synopsys/std_logic_unsigned.vhd b/lib/Standard/synopsys/std_logic_unsigned.vhd new file mode 100644 index 0000000..3e29847 --- /dev/null +++ b/lib/Standard/synopsys/std_logic_unsigned.vhd @@ -0,0 +1,329 @@ +-------------------------------------------------------------------------- +-- -- +-- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. -- +-- All rights reserved. -- +-- -- +-- This source file may be used and distributed without restriction -- +-- provided that this copyright statement is not removed from the file -- +-- and that any derivative work contains this copyright notice. -- +-- -- +-- Package name: STD_LOGIC_UNSIGNED -- +-- -- +-- -- +-- Date: 09/11/92 KN -- +-- 10/08/92 AMT -- +-- -- +-- Purpose: -- +-- A set of unsigned arithemtic, conversion, -- +-- and comparision functions for STD_LOGIC_VECTOR. -- +-- -- +-- Note: comparision of same length discrete arrays is defined -- +-- by the LRM. This package will "overload" those -- +-- definitions -- +-- -- +-------------------------------------------------------------------------- + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package STD_LOGIC_UNSIGNED is + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR; + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR; + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN; + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN; + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER; + +-- remove this since it is already in std_logic_arith +-- function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR; + +end STD_LOGIC_UNSIGNED; + + + +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.std_logic_arith.all; + +package body STD_LOGIC_UNSIGNED is + + + function maximum(L, R: INTEGER) return INTEGER is + begin + if L > R then + return L; + else + return R; + end if; + end; + + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := UNSIGNED(L) + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) + R;-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) + R;-- pragma label plus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to plus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L + UNSIGNED(R);-- pragma label plus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR (length-1 downto 0); + begin + result := UNSIGNED(L) - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: INTEGER) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) - R; -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: INTEGER; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC_VECTOR; R: STD_LOGIC) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := UNSIGNED(L) - R; + return std_logic_vector(result); + end; + + function "-"(L: STD_LOGIC; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to minus + variable result : STD_LOGIC_VECTOR (R'range); + begin + result := L - UNSIGNED(R); -- pragma label minus + return std_logic_vector(result); + end; + + function "+"(L: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + variable result : STD_LOGIC_VECTOR (L'range); + begin + result := + UNSIGNED(L); + return std_logic_vector(result); + end; + + function "*"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + -- pragma label_applies_to mult + constant length: INTEGER := maximum(L'length, R'length); + variable result : STD_LOGIC_VECTOR ((L'length+R'length-1) downto 0); + begin + result := UNSIGNED(L) * UNSIGNED(R); -- pragma label mult + return std_logic_vector(result); + end; + + function "<"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + constant length: INTEGER := maximum(L'length, R'length); + begin + return UNSIGNED(L) < UNSIGNED(R); -- pragma label lt + end; + + function "<"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to lt + begin + return UNSIGNED(L) < R; -- pragma label lt + end; + + function "<"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to lt + begin + return L < UNSIGNED(R); -- pragma label lt + end; + + function "<="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return UNSIGNED(L) <= UNSIGNED(R); -- pragma label leq + end; + + function "<="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to leq + begin + return UNSIGNED(L) <= R; -- pragma label leq + end; + + function "<="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to leq + begin + return L <= UNSIGNED(R); -- pragma label leq + end; + + function ">"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return UNSIGNED(L) > UNSIGNED(R); -- pragma label gt + end; + + function ">"(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to gt + begin + return UNSIGNED(L) > R; -- pragma label gt + end; + + function ">"(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to gt + begin + return L > UNSIGNED(R); -- pragma label gt + end; + + function ">="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return UNSIGNED(L) >= UNSIGNED(R); -- pragma label geq + end; + + function ">="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + -- pragma label_applies_to geq + begin + return UNSIGNED(L) >= R; -- pragma label geq + end; + + function ">="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + -- pragma label_applies_to geq + begin + return L >= UNSIGNED(R); -- pragma label geq + end; + + function "="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) = UNSIGNED(R); + end; + + function "="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return UNSIGNED(L) = R; + end; + + function "="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L = UNSIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return UNSIGNED(L) /= UNSIGNED(R); + end; + + function "/="(L: STD_LOGIC_VECTOR; R: INTEGER) return BOOLEAN is + begin + return UNSIGNED(L) /= R; + end; + + function "/="(L: INTEGER; R: STD_LOGIC_VECTOR) return BOOLEAN is + begin + return L /= UNSIGNED(R); + end; + + function CONV_INTEGER(ARG: STD_LOGIC_VECTOR) return INTEGER is + variable result : UNSIGNED(ARG'range); + begin + result := UNSIGNED(ARG); + return CONV_INTEGER(result); + end; + function SHL(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHL(UNSIGNED(ARG),UNSIGNED(COUNT))); + end; + + function SHR(ARG:STD_LOGIC_VECTOR;COUNT: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is + begin + return STD_LOGIC_VECTOR(SHR(UNSIGNED(ARG),UNSIGNED(COUNT))); + end; + + +-- remove this since it is already in std_logic_arith + --function CONV_STD_LOGIC_VECTOR(ARG: INTEGER; SIZE: INTEGER) return STD_LOGIC_VECTOR is + --variable result1 : UNSIGNED (SIZE-1 downto 0); + --variable result2 : STD_LOGIC_VECTOR (SIZE-1 downto 0); + --begin + --result1 := CONV_UNSIGNED(ARG,SIZE); + --return std_logic_vector(result1); + --end; + + +end STD_LOGIC_UNSIGNED; + + diff --git a/lib/doc/Fixed_ug.pdf b/lib/doc/Fixed_ug.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b7783df2d932759fc57d52c3bd8e85f44c737f7d GIT binary patch literal 80675 zcmce81z4L+vncM?Qnb+G4hg}v#ogVCySo&3_d;=pLUEU3#Y=H5?%E7T| z5*8K?9e#dvV;duIN9ZJfexakdIT)MVj|AdCM*;qPF|(8WD3RFws$*v1;QCt~I~&X2 z>bST#|5^tEg1{4jy#DA9#LV%xXF=?&%zuSr0Wtr*j+O0i{jqQW|JEN12Pg2a{jst! zv;DmeOsBu##|B~n{jH9RmE*5<>}(u=8-s(H`EU4fu(1A(E*xB-zv05k2KpPFIk`Z8 zdzOps?=;}z;`%Et%s?RLUvXguas2&RW@gU6jRAzn&%fy6y|R9@<>YMv1yfC&=F_)BN<;pz)*)>9SrfXFYpWg;;)a1kqvL=cx}urJ-QZpm1^or_oWsYUAh3e<~1mX0UkvnV_u9 z|3pbOEoKt%TL;X2BV#u$uq3guvgiQr=`64BVC@KIiIA<8v$c&Q2@6D!jLZ$4Y#qS5 zjGzBrz`*(spzLmE{6n<?r-r*CKsmIhNt5+DH53f8qw4$j74eB_*+tiTG` z5iB=9#8}4IN#97{NuPujLJmcMyt%QV@z2igp9Jf2NXPn)PBOMe<|gLGMl{0QARv$p z$N>TYxqu*MR$6}W3m~s=3htK`tZ^azfN!Mr-EEzn0CG0Q_v8U6fsrtDQg$#lzF$`0 zMF|G|K^Y-14pz3N|7M(@-5MBMfd>Ms0}{nQECSeofGh4PBIICeCur-Y1z9uf%pel5 zg3fCWSUZ&)cBJK8!s7#jbSB3lO~ z2=gE!r3A(u_@fgraYe!SfGd@if#3<;vr1W+84Pf*jg*x^;PS6}7BDtoBLblgSRQQ+ zm5iOV0AM}>l#Sh-bO0i5PGU+Bq`)1D{TSsZFc|y?Ga$_Sov@G@g9)p}1~G}?IsG!i z_xJZCS2Q+s(&7R#f$`%2F+r3y3o9EFGnh(joNP=WHXVSHvw;(25r8)UmHs2Y>MOcXa<)*uREU1`Gd> zK_FxlHg+_0Ft>v&QFb8MHiEeik!~R~eejxPWe2F48#$RdYJq+zdI)(TZ%!5njab0n zkk7B$Kg0a0gzE!&nJFC{rSoU zW<3Ok6}%9BUBNX!Ye7GHg4F*}`qc*f@eB(m*AFZqFpw4qUOynfWk{cY9_`=Vf#<6O z5Y%@xhEN!wY;JArC~NGhXlt!+Bd^3LXlrF8qYT!r4nOJ40s@HGfDM(ojVYMkHUc(| z=Ks3?7o+~*>AjfW3);Wu>AhO{gQslFf95IckEIKl5rp2%;Jwu^zW$g$J1f{~-q%5{ z5c>V1%YSvfr#l4l2Q;_`wx6GSNLEQq#=h?fg6BOKA*CM@^79I5|22z$;R|kqlp)mk)%NQOfrm)S zk9mRNAoY-Of3^RolJcWJaG#Lp?w^J91m4|&SMz@*KL0bxfk?wo$#F8aRwdyC{ZOW| z`qsvOl~c$-VDSap0%IpbGk~nEgSEcZk191|b5k?0u>b-gyDYF>Wnl&H02~b=7K9PR z%>DyN5Te`}+1NQr7+Jtp0_-h-r3(n;0GpnBNKP*B4g)-ZsJ^wil{?LkRYC$@CL}-B z2`xZK-%k8~Aa*u(fcnoeBO6#L{cBPDp}hbSV3TQXC}3l11vW3gFBXV``F+aFEcXch z)13dcHvij+bNt^-ob6u|XJG|T9K`|@ZRdbk-!paXpBkDY z*AJk^l~@#fDU>N;HUCyGn?Oo6fPfq>)beHK;(#by`YqP^w-=c&532Of;mgZSFdMQC zp1(gk`+9&2gY2B09i(@DOh3n@p43^&KuJTxAwXeBYYekV_^vp|v)6!zm`37Sm-iK{ z8L^@CTAvo3ihY%DDb1P@^d=M1v)XoR`0KVWqO)md03|I>P99#1GUCaQ`f8F7S)E=4 z3(rWZKBbg$$G5KZdVa-bt0S?nkhKmAX;6;q?tiBBhSQL6@R^-y<{U~=ndKE9Z}3!j z*@c`;UDS1s_aocm(PZAq?f@Ebn**GVve;N-_jD6Q`S?UP|+L54hDpZrf6S!*4GEn&P-F^LGdUA z1}hOVv7{??nhYNCPr95vILWn)tOywNyx3A+)w5!Fy|=q@4By*OXw>@&iTHiWR#nWW zhm6B^?@ho4T>u_YtR zf`n2XZi7{QR@3#Xlb8$+0kb4&>jTQqZ8^p#SHpROJbgeJ^>@uX(0BwM1DDhZGDa#d zDh;r;;u$1(HxWcwI9odKqor5fqR%Y2>Qd=3( zUN?U#<7i}S+T7JWY*+rE9m<)a@2%-JQraNn1e$3SS#lhFHm$SkErcPHg4= zM!oBnU>{MvJd?!oTb5G^J#PZfIS`kdf1=^lPz^Mj2eh5(SF4%FmC@fR_hke=$e_Ow zU$dO(~v+6xC2XSdikciE&X`1(N$w|y%4m*8PLpW#ZY0qHY@LI!IanJ?cv zZ3_&-N%nIr_Rbz*s&@p_n`D#Ftb6wdN1`}g2lEG8PGc))kxB;KzRuCOKoDBDv-`?} za)Qo&8O>!vz5kr&b9mfiedhDKSP#sYixqe|J4bBZB_CZuxP}H-sqOiR zGHA6GnH5Ya9KN{Vxs=b9@^cW&$sk_PBfCFihacTOE5KZ59d55AJk^c>K6%*}Hfe>g zsaYPdV#kT3WR$x*9SFw>c!|Oe??taWMz%S2yWoR=2ag;q$q;*anoe}~I)t??K7K7v z7ejdeQO(U1qwL310dx9^h$^Zl)z;3dq4Zu<2J(cD#gFPlkezzzpUL)lf+XKxjT2l_ zcR)S1e5~`2!u-=i0s9ocbT#Y0)74f=12*eGwAO8Uw?u?0L-zrgM|`!&u^5_q7=i#6 zk(Jr-G6@UB`o|nT&nPw-LIj{9a-V#Ak_?y4BJcM!5Nl;bBLXVkd_&G~G>aTs@s7Cc z)a>jWEpGte=Jxs>Ups?7Mof&H)G6QYn6M>0%BjtUelSV8l4kW9lGB~8KgFqvI9z)W zQvnAK!iMta{A8q;Kt|=y2`^}*hpBu>t&#Ls|6I_O*yD1?6n!j_0({rTa_i3yr*#grA=ou`ND}iw{Y1Nh(=r-mF<9 zI5;XRbAN%CQK0o4PdqfT?^Sb@8M2Ai#X`UQWcr6K8&}RasW_L>8T38}`BgGIVl@6S zNp17uUCvGT#k^x{oHrYhbBh7r{R%D$URCvPXeU0$jcG}s%O0k?z~mwD?9DxDDm-&G z&VfI?)WEh0>!r^HvOXajf!pDlten>~XDnjpD!44cieu?OltBsR40<>Y8&-@Q62Vc_ zllL|BsY8lgb>1o(QBZ6+j}%>1!6M1IEY{!_y`uyF1h%Mm$1`XIs4wMoHUB8e5D)NA zI+u-&NHwEG3mF&0?~fNgGP{C#j93sY_Jt8eGC!JF}r|@=UsB zU!4`~dTBIr7PIvNV;K}7Qwa&44Jyj%zPB*2gO7x!lQJniI|l`(6S;YG9{TblgYiFR zO0<)m^M2QInYN8l^d8|uPw?l48F*s)V}&sdn3+i#n@AOgB95Sz&=XHd=_MJV=*Ggk za#KH}HF+x9hg)x+qoj{5!$!XzFATOx*dr>j`Jjm1x z8J&bwsYCLq;zB95sL?C`$rlFDG}+OE)_(HyUV;pEMHc=kmevMH`cc z@W)WCLZMEcN|{i<-}U~yN?CIUGbr~_Q&0_Y^2vB)P%0M54UQhvzU4#Ae-yX>AXvf- zaVmcgmaqYTIo9_M`u#Tq3R3!i{rRuP`SZxXp#G@+Rr6Q;?je4CL!f?@{|fm}_kZ;N z*Vg~K<#)*Y@&5b`Y5(Wc1>!k_z(Mz4o-;UL^qc4Wb6|+?{JYo8 z#=-fU*9^Y-PrPPu5aq9m7s&B%6mO}rjBVQUADi7q@iPzCZ|dR7b(Yl2BW#54cqh|o1hy_5(6*P* zqIs)}M*Q#uoo=2iJsVNS!M)U=H7$W5&yey*d3#U=Y26<_9D-$uDR>Inrbm#efA8x46*1n}64m>ogH~eOqta>& z7j>8H8bZ1V=MW~xQ}Stb*C0}cM3i&*&Q`r?GNb5XEboW%UE~7lvufo+FI?5RPOZHb z^ju|(`8Y%-zadnk$bF6OyB+tHSR)NqQjU)APq<(j%TFwnK&P1u7iEjpE@I{zWlmVv z#(G9}lL$BUM!4D{gw}h>^0tMg#I?{cPQY|XM9rUKGwz{+>D|HXN^JO7c;jS@>iVJR zO1+Z{6BnLqBx}_ip}gbwAN!di{l#On7M3#Qr79PsAh=a~y+Y|`C!ade*cw7OI~!OpNidhbik ztg?3fB_n8DbFd`^kXFPt!k%V{kJfxzZN6XVvLmX{P+8I-Q%~QXl;+?HcSGG&UEYk` z=?b>o6G6nB|D;O6=L~-pAaIoE?`LzrTkb?9DTw86gII3;Ia&vnZpmz>;^6m5S!3m!_DhEfy#m+nD z&W~KE2n!&fra3C%@&Jfi$z9b5OGK4&+GwTTPyW)^X*nRoH8c-3tW1HbAvg>gp?&WI zdZLX=DunYXh%pQt0APDwYCml$UG+QPgS&0i$v9r9Eo4VM?N!jR)%Mbwnts^VgwA-qlw;4>6^ zv*VhW;!8XzpDqRjR8)=uT%_pVE}LIHO^7{AO*XBu-;4j%;eXty^3pwB*bD~+(G zPS%XRDHY!}eQ1YXzuj~(ZZ;M*i4fEE{Ona%<-9?2S#2(~=6)D49aEFVKma-meypQ> zpMWKbg}&dm(mIw<*r1LO{@2xHg7XCV5M7~5C4s70bhS#`9Fs?eTNzP`0jla_`hraqwSBg3`jKi=iQ(BxQ|^!TJN9w1@|k8{YPKF zmmp95_<&8{ukt-^kUP-N-XK@ViOequ$n`#A4~ZuKh*d-S0hjN`2bX>`jsgzm`d0rl zs|YzB`O7999Af?3G5qgKJy3aBZXSr`J)&#Bre9q^bw+9LUFpv{hk_%(#(WrdK+3w? zFN~e|Nd4}5k?WIL5iZ#$zO0eui^U8b$4weJ+Q<$DKZa-G9q;^M@c1V6sD?AtFTL{% za8V^xku*>r6NDq~=F&VDB^zOX_^Ll2@Oe1NAPYr3)D%=wPcb7`Z}#X>LRZPg<+8|d zQC7bW3vQo^6|mR0LH^its0Nh7=B>u1oeBe|jMpwt0t-cciwG#pk z-IXl=Q{&T^?EpT7k$5Poot~Wc7mi5h4^(2rX=&y$)1qSP)$i~XQ_0DWU!LweD6xJr zM9u23+Jyn^?-iKMRhQ3AxXq@$0)F;EE;w|_D$l^X`shgAn~u78 zAllrPO-&Hd>_6pLw~)xz^cMHY4)sggl{OkWZ=u29^&0e%Q=@&8?f65p4q2hSU5c$p zN3yh`p;HG*%yk#2h6%t7>?M0kx*RoZ|D_K}$f4tYc4(Lr>=>z*o~M*73-IQF9#j`4 z65Bs20LVe`pCpcj{ohHPXDpvw7Z5-2Li{G=F?O-b7tSHXN5S4`Bq|0+q7NjM#L)fo z!*x(@JU+uAhbz9jd@=8F;7PHeoDUPI#P7G@f!X$LmR<(BNl6nP`>BXhd$Foo6!D&~ z-P6q+rjH|~54yeMW^CqZ9(@~>I-)t`eNSTume5fNo6QHLc@OaPTGQs%)KiE*R(00X zNllf^amHeZZ_tNuWC$x6WHo$y3u2GtX%gP9PF!+e3*l(%bK-t6WQ&KzY-3}B`jRtY zNnH{eL&M`Er9KmEgS{aAr-l!ul`_H)YA|*Ap89z{fuk;3sYJYJ$Hurz{-_~1K_S)g zg-DFy;F7Cw1~`B}XPRCu=KO@KHIqli$uKegtd(BoQFCf6fJx z1*fG5Kr)1Ez-Rv8V=EVPLt{lT!QYirdXl@ck}GbXkL^Ha?5oNyLv$_QN`zQ8EB!cP zI0YmLBn92>yFs8ls#$nHZdpn%9xHHiic${Jx zvZjR-hffbLxGr1|4;PnPFEUP`vZ)J7>ZX9GP*Ky_Ba)FlxHyjt@{yrnQAl7OK!M!L zm>79T5m(}Sr7ATSkZ&R~Um(Vsw~|SJ=l~wwg)z?TqC-6=;6$WJtaC``u`e&-*pWUb zNOv!IMHQ@oy?+d6U(Z@)k=eTKxy3ctjS{8mS3_%>A(#g|HcwZZA$Y|}Ud-t_Rs8CV zQ@7_+!G|{r>o*IJ-YR^sfPTJ9)gnL(==+3e+RRTa<$nSL)$cULqkV<(I1wFTqJUzm zS+rGC#inCn^T}%(R^>=a+WohQ2mwGLs*1#2oY(o9c?sr^p=9;|aQ|NNblbTpFH8_}G*waD!@V{cKx}55?CFw_@n3p?;hZDzXBuSOHxzi&)9@73ymPD%9pUlwvLVvft7ve9`^2=dj1(klN% zo@!ZYM1s+#oGZb4iVTS9L_QL;d*X>)?x&^qP&yz)4}llHf&__7 z04)?%LjWU|egpoSkO9rZ@DRluhBr`je#)`9AVJ1alsAZbA;CGsqc%GiqY684P8iK_ zUhpyknAwNf$v~J1{U=t4EuC$Z_|bk!D@1O{rT&&HRE^j#5HUORj`%Nuo-q8Fx&hRy zAx8`_ScLDzh#ruViBgDjD~2YLdgSBmiXy}*7(H`9F5j`LTA#72okwCas(2cAYV=dP<&S6GSn{EE($2) zCQ0$|n=mwU;A>$95>>3Uu-5LfZrJYiZmI5;ZjFawMj~IyL}JG!K=FQ)B6EUsVpow) zDXcOcvW0QP{ogm>97r{!4oEQLFJhlj>QXI}x93*UlqUiuxkUub^G_9eY5HjJXeScY zl-X6DM`drx)4%yLNxJ8~N3dtThfNr@C5&2NJU&^wSxY*1XqGimXa?9JYNpl^1mr&6 z-QRgS9y8IN`%E8*Zxd-IO4`+--ZwkM*>jnCybx)*Wk|)Q^tvu3>NPQYi`DsS3H@e} z;cKZBnU4Znq+23e_#XC+ z;^}J3als9p_tQI)JMO!JpbU}7pmBq!9`A@j+z|$AhCIesNsCE{3>6w}weL&U%IM12 z)uXf)t3=EA%2>+w%NjJYs=ST5YLFY^=AGt=YMaba=RM|3KC#bx>%HuBnI2wZ8k03` z=s8GSB!AiFRqGXW>w8;tj!D#r5r<(B0v$3!^gTSqkXapvJusu!gvgpWfha1PhlrX; zmkT-FA%i;|gLBcokUJt{FdZ>nj(en$voXJ^w(+xb)2^gFPD@gYjSJuY)km3?q{I3T z)(cF!6%bf)A0~+n-lHZ_=~s zTtq5D(&&y39S~=zrucf>KLD0NjY+dfjm+1B{YuJJ$~0am zKAAF0HmAs_2(8F7VK1dbjxPzJh_c99x}|m0Imczyjaxjq&{n!Vfwce4z@-osGYh#R z#R)(ow=}7==F`IGwaC(U=*rvu!p4`td_>?Xe2R0n>1Cnw3*B2VX8a|)AR01vX_5|FOzv+D=uM_4g z{a#O2Z1A$D=ELa+OnRTv4;9?mq?VGbVs%8;1?Nt6Ud}>ilo`q8QXCrCsx`$XqFK4i z8mLoD#e4=UtIw41A`g0B^%ghxH^((^pShof5YD2{1*1k~Mp+UbvQe_$77|z|ab#K9 zTbbLYXyVpbiP2AL&UsW1HI>y^d$_NC)%h}c{^9(Y^QH5tt7kizPfwL>%kXA~s~T1L z!o2Zx!C`Y1o#)i~)Q-j3UKks+WqqmpV%g63+`bCa%I%OB?uU4mB9D&*si%IE1Zdr$!EJ_u5;St=Ctft+HRPT+8&N4WlDq*epvgS}pK$C0@xv0kxrBzmVS|8lrf(9JhMEDI4dISD%(7JHb*R{K9?#tDGwpf zC2uQVHNUTbv!J+;urQ+Vw#cSv<&EN-?qZJO;u4~gn71%*o!{=3YL||d370jNGnVI6 z;8sLbLRC6f?p5hkO;<}*zpvq}DX*ohO|QeQ3$KT+cdtKcFl$(8)My-Ql5Be4%+p-g z!qigqj`UqxD^6=n8%kSX+g-ay`&oxw$LCJd&h_`Y@8`SJyC%C8x`%tDdir}sd%OAs z`r7;X`ri$34>Wz?{LnDSK3M;e?PJ{#+fdyw`*8gT$4KKS*J$$??^xUTv+>Re;fdZ! ziOIn!*{QKHK^Kiw|g0qwlo72O@()7snIx7)w|9Q@_Mm-GXggWALA zhaZpBk2a4Tj_kZ<~>s#8} z=I>J97w)X@?!d{?7l9|&DF3*Zg@gz0cboTdU~q0cBp~}ErRZM{_5W=E81#Gc)O}9W zeE=AoVgpW|0{@!eSMt;!IYeAQ@QE&XfS<`zKgRq$_{+ikNAMT?+lc=p_WMWV_a767 z|GP|K(7!T;Ng#m^#s4JT7c!flIlcEWd~h!GkDT6LdA#5>yZc<<|CK!6zlA4RfL#CX zWU*Au+IF7vAvmE);B&I%yyOGj(ao3k2eA$gc``32j7(o_;(e=^R>Mj`@Gs_?4 z6U~y9-}QTmOWSvoe&c01iDbI#S!!*$xtxF6UK4nGwST?rV~B^WrEND|88O)I6KwzT z*xSLLD}^GmX5fY_EFqAdJq1KW33T->uo?$tt{h_X%G4iWQNsjFaI8smI^g5_%Nzh~ z{O?MIa6W&kMTyYsDWT-8(|=OhB@Txsrb6Q{_PW*o8SZ!2uQ3sr2@#l2S3Q%vQkuAG z_{nC(B6lL=heP|Wj~U#xH;g;0t0M;);@t9A;##kRzD(<$pKRr1R?U+{OmIlI>MM9W zZZlrpkefm7K1LRO?m!xk1CN%VZ0OMV7COor|2W&EK~UUH5eX?0#}bL`Nu^GI!U{&F zMSaL!8hRNFk938}<xawm|mT_7?p)Dbj6`NeJ;nAwa7?O=h$B6&-n5f zpllVM2EH{1$ZV$8P1SrJz^hK)W*&hOdG<1<;vlt$_&d`~$OGJ0St6fmXnN%m3fxi^ zmAJ%A>Ul1UxV#Kw5k~i{Wfsu1U0;)`F7KYz@5;X*$UV}JwqfyW<*I1dI}Zkr#e z_~KfxIlj6Mpq}b@OK|~*d5I^IZlX>Gw4v&FE|t=tPTJ10vCcE9CB((59|!Xh*lN3< zr2j}koCwG{iV%rR)bL!=Pxxqse*-kTf&^QJL0(Wax{HFB5K|707u z2NP^uQOv5m26F3YAVDA0tLxYMJ?N~3pH#P z%3G<1_bq?yf#j~24Ghhi{H7$G4_D%|9lbY|711UN{0(o?vIX}K&s>UM ziNj4rzQ|sJWn8CR0Rh?Ok-AB9_b!V%<-r7@&gUHcfGm@`j;D=$-$%XX zEgJeltm`bNS!D`*w~}b!e1l%pd>UOK-+wXR`O=ls-#^N7>t$+|fgi9C>2k4BErrX#kf$PwIGnLv&P<7^Qhi9Yi|sd{nk zyGyy9>4-NKhw3_ty6!VyazBV@8#Pnq)?y>}L)mLT_>RN>lrWVvS93ajTr{5zlQmdU z_E1#*gu{}Uz7|(^?$oJ4*KrTZvOh?}w`7jZQZ+zCamlu!C;D^tJnP;lUG-sA$b|CyxO!kJpk*4Pq4VA0 zxOdqzqz<(CQcRt!Bb<@SeR+I|dAu_k9jvz?rapMx}ciV+pUqR8j6gJek>prsPjgAof^=MYD`@Vd?_B|`c_;ox~A!e}3x z%H(nxnI|pDb_br#A@U-n*_K>OTS|)uW7iHvw?Z0zk6mHTiv_FX)u}$WMu3J{o>NBU zybV@u8@;PP>$#aN9LKh#%hE+53)${9f6jn22i8GVgzYwOqh6iXB%Vr^><1QL2xH+kB&|3i*B9Q=SK%9z45p%_ezm(oSf_l@cJS-qk^%D#zY4vHku}% zO2lU02|6(dlQT57gk$3demOE`=)Xfm^~EJx=<=t4@}Q|9$6e@+hHn@XrN3yHQ)R`qOrC*Eh@P^^bwu@_uHmw`4ydqeCJONTggZk*Idvl7##R7(VZd%#mJ=J?dwsa zgkWoyDLpZL9!ozyHi)>NwbBER4mrDoz6zugzecoe-2R`k1^y*p+U1S-H7id_sM% z`GnwV-lLbv%a4iA!SkbVG~z*qVzw#wDEV7iA`uS`(--Q&3gtWpO*~sHlkR|zwBa!o zshm*=CPiZideVj>PfvnSOvwq$9n7%!WF&7FGqPRPhf%YyLEb|ov1lfcms%+oG%INZzN<3&gEPLvApuXTPL_jT9K|?(lsTUBW zgazf^?$B*odqn05v9HgWFzl6Jal(g@fF{8xx5!;SvCTvU!xFF^ zls7okn*rL;+aL5difg9{!WU43;_cWBaf}h{O&QrAHRJJ=b}2qKiwVS-de%7|CSUYG z4yABpQDMJelrgP8sIr^u#D=V?hXFyp-@Q^Dy7LU}dle?8iaNptsamH=SdALz{xz3myg55;Gc}ICL6uf;r0{-_NOqk0YhSuRGm!-X8bv36WOmgu+v6)Q zBh1SPfM-vqVLvP<%R5i?!(^6f#-nFml3&z&j$Uv=y9!mfa@rKS_M$S7_pO-rwoR+O zNL4xprMg4YmLJJLUHjdl6@BknyR5_CgFn8xVh@FKcw@Bx+F}6L3&RD45l&!p)0QH`&r!jzWm#9CDTjbo2_)&w=a2%JK>F_mukKP$5*K&)0 zi}%8T*=f~h6gmB^n&I^5=BP_FL)jbW0J0Dfc(qrZJ4~F0EcPU3`S{C#K%4Z~=)Pt3 z^Q+3CfGp%7=BSQgo+myErS_RVnf!TH`0>2q5yc$Umq*+qM-${v?Y|e-%&$|G2N&R{ zK4Pz%p|8VxEy-5AlxY*Tn)12T2qW)nYuPfTXU|IIHJTJTp{gtX_Xjto+|cKbX7u?p_*iq%N>xQoErZ+nyX)~<&$kNOyDM4FwW+rp zhfCosVpb#h{oS9wW%+b9a=)zM<+?tKft5q)#GL%|I?)e%j*His)JZIVV zHKUZYm6-kxD|uK3ba2kY!3xuMt;6sX)6HbbVnSH^d~=PZRW7_!1`IM<;TK2qycr^@ zsiB|VH<;zTX3X!YsbDECbE>x+3e`;{sP~lm=Jl@Y^>=qwtM1RsgY6lNJ6OOHF5&!L zEXg^|W+N|{>%IM2f28G-YFl&Tb-fw$lyECt%~zo!b#gNr@37N^+RAIlD!RFszVr*n z%dHjIcDLwLNZbfE)yEry$_|^yN!^ zA&0s=d;5Ii*CXy?Y>eo4?{xHErW+=`t~k04W=EIAMJ`hgdWqfk%4tS$ zFrNoMUniKX!tea?u0q6eCPB)jE}sEsJbt`u2Y)m;zl&DF6_2bsN>S~{_E zDEJZ*FXNG5Q{yRJddFLZvXWh3($u>TctN%>+_Q&QrB3p)o{OnNyQ{7LtEQe(Qoi9{ z!1bQiyC*1af`)po6+Y4?oD2z|;$mnjjhFzscl`}rv9Ylvce?PgD^S^RnHwja z1kZR$KAcoopS;Aj;6f$thaRY=&;ph4I8No$1gtDU;usnZW*Dx}QY~mn3i0qpxjZA& z)R|G5l4-suutCdNdTLQgV|FEFpI?_&n?6y?fZ;A!i$dgAM*1r3&DxcGuQT0;E)2j# z3f$pdze-V}erW%z>drOI!sn@mm2B}1%ZJshDI};%mns;7$k%hn&p#`(dS!K;>5;uF zz@F8|3KA5XJ5RKHxPv+s6c51C_n`O2b#=6#H@&h>?pr_RR(VW_`f(2FUxUM}pL&=;H2%zUB?D*ssjQRwy%%fi4}EyXV9=HC3ZS; z^i~tAy~t0pM|rF)V(=6FDqyn}tyr8(^nvv+PkcS>JIIiJQvOREJ5H@SJ z*LLhe=awR!3vIl+#X)xi)J2LOXLjT4*Dkttcnl1o_-H{t7oPB?iD>K_t_6JHR!s;L z5`6}RH8+I>=*y6%V3S6mf`-W*6SvsBEUG&^n{UYe93uARy+O4Y!9fCov!pRkj^WXP zBJ}NNgwW^nevPpT zvn(Ye8Et@*vFGw~md5HjSTGog9^LaxFG#&K9w?yqRaRH6^Oecyd$rjj=6rp!d!4Qt zqI0Vw#$V>BFOz9%xv1LqlA0WgTBe78sObHHL>-L-Tq^c_TA{Q>?z2@%Bd9rI8{|OL z{Bviy*HGlyWOK~}NbaNN)<|I{aJ`vznN7I*gw{~fCJSvey_pn?M|kcixrw2TWZm=l ziOEHJoeD?KemaY#L9zbTQeNQ(g?MS)S zLI#P=qUAGo)b75D%JLV**GF3uMVN=WKA&Y)X4b!CUn|2|P9b)Dmp}icR+v5T&6SvM zP9w1UESQ}3{nJ=zt~Uy_sYIkNf)RYb5zz46$s5DZq%wMLJwRp*H&i__QQ%lsK30=_ z03?o$7{_||2(3&o1#!{bYb>$jjJOcKvLWT89{vO$B%o-VGCcc@Ca-))E2FWGNl&Ar+f^~3}q*yKz3CM z#Bh$lV(t_he@JFPv2dXmS4GJ@Tg7%dkSAm)Co%5vj=6QB&tFyX;aohqdC$jI+5E=? z8*v0pSlCMnaTKRm#13VK{sm`#nasGFpF9Igc0_uKTUtoHRcu`H(_2QL~tY!R@Io5&$ zl~|CDY1DFx4{qw(QH6Y?MmQU~b@hjSo&0C2cHj|0c{Iy|vIbx#ma-Ql5w z**L3MgM0(W8OhBYcTvuSGW}uxcyU61TB)+l(VYt2X13P}&)T>Oox@ri#f*%~+avcK zTJjkep$6EI#)a@Ub>g;woGvzZZ4IOkk?bp&460WtQyK^>GtrN~3-m}ntI?JMRO{#t zhV<<5L{D1)S!Bc|0zN7R1*De`N*BY9m&xwqS}1EVH7n|)NH@_+mdmOnSoM=JiNwFi z@>%siJ(~Y!wdyd=Pv`7KdaUW#>ibdU4M`(L-=had#^X&zwT6N3BnSv&>(buG_9`W^ z>8)tYPe`-B9;C*6A+H`NVn~0{ZdQcQLsPxDX zxwO%yOn=fN(A+JhhRo{FWicP20Yl}3cvom6DI@sMXkn4`8=0zWS@!EJOS8jA%IK2J z<70ZmFOi09n#`Cn4n9#P;1`BS%qB3SHAG0y@b`VQlq}-dwvF&4iwW7qr*}f6$MC?R z)fpdms@$LLJ}fC>HuhksX_g&AbH+wdD-_M^nl0S(hX*vhbkH_oVpT)a)DI48yN4Be zhnS8O>c6R{&58H%WAxJ2VqH(+M!L zQrz8cF^{j#&ib6tnMWC0J#m&z*2XDsC|4O+WCd!T+g zgZ1ui#%>cE0h|`&v~^G9iEV{-OD!_s?vJQNtC!xrJUhAC+m0Fa;hQ@xld*o!L8U!% z;#nUMhc+-9w#6Bt4KNzIvx;_Bn0|RoeN1~8W4)9tb89i2$!lvn8;=>#ixtzaO4#_l zM+UA)vOu+&Z28t#`Pt0g%dj*m4YD=iW&tCE(=@kR(b^LFb{hNj(07Xw1IuX*YaGV` zN6C&a0!>@p^fg6of}cI;YuhjI&|TLpaJelkMLpxhZ;ex2dUf5R(KW_Fh{3{vJhUq# z-B8I~Wi6vN)K$89`Ir&0_^}6oWAR}iyUv|5t)aUbe~H0FL!U?5g~hb@*Qj&jHIJ&p zXAR2>Z(TyX2=NfEF|EBDHE!I8Jv^qHT?y>GH>k#AnAW&>R6a*ZNTAZvc2RI9Ga88= zPNFVQoMD4bT26H48OXL9)xXI`3HaTiw>sUDIb|NHt`@gp2hD9pOmdCW%Q&MhKVUTz zClu&BQV__U)r(Ugp(t#Vw~6Mz3jVUeNo<3&1;X7YrXYS)w6TK}?$UJUo7Ae`dy z)K4lPi2%NcG0jYJcb)=n@CJ>iYLI@NrHKajPUB7muUfwEBj$LbfBn}*ID!~Nk(%e8 zHbmTqBL4kwk5W2zwH%T=Lq<3vdL+4}#+GRngf_&W2GeZrr-fj_l}|v<~7Aj=R>_g^D0+V<{fzAz2Fg%&LmrTAxxnII;FC zb|>|3hH87$yp>$AAV$jyHno6r9{mWL9IX(0XgTfQDocbOEc)iykhcIBoMYdBts_D2 zo^1Sz97LqR|8NqQaC<{IMpXhp4|m&7Xc2PpXI7O$&i? zxb?8E$O~r=nIew>vj~y$r&Z1@($>TI<6F|p!06zmAh##@&)(R+iApJt3T+wA2(iBg z5!Poh>v?iWlfT8&87(B35*Uk)zTjrW>G6H$q>aT@9C^n%FOe>$SS+Q8)u^AIzA;V_ zcWL&Px=OtVmm?B=Qo~9%3Tv#x&|ZHKGyJGsy_xO~s3>|x>hsWegg?oS)1LM9V=Xis zwa0IAfyZXuaTbGLC~#1;(2@hr%NH=CHBD*wYr{M$CzNdYNP1K(K};@ApS(sr_8eak zA?Am*3v9jYj!^&5Nfpe*#N?-2dKgW7G~A2HE`ZfALBz~8xDUnc$y{x$yOhSuWe(?7 z!z4Q={7s}U@(fBJwMJuZ=Eb&~d(8PaGIHzE5CbS%_srH&6$CLZt(%*Z9@}%#oCw|U zHN-^foOhml@uqcI(~%4p~d}FXw33 z7ZgmJ&__$S1s=p1hodKF8ZO~d(qTYJicR9F6i7tFdLM~I zs=)KXMgkFsKrl29UE3zDok*gb5-nohfi6nU%xG;kuHHWxy6AhyHCfj+kY~E7iU={x zrit`wQi3nDawLA#A9bgLNX$h%mFEi?5`oYd)@pjA5vdy^Pk6Ycd&yEpLwc;baU*rG zl`;#W4@u5T1<<#|VG3)$K_Vlg-ONMuP418^+F~On3ErlKtyg6(ef6sF_>;p1%Ph?| zAJ0$iciqMJB*Pr_ZY zC*{Y4@USpLSr>c}EN()^6O*}Hx7If>W7MlDFGSiFLEjoXvi)rt$jn9IBmXdEUwr$(C zZQFY1#_bn9FQ(s}m^&S@|H0moJ9FjAZxJL?Vo$i**SAz6);b}KAJ=rxhT&x8o6ra^ zV$sZ?*Lh?F4}J)CoAB_PIJ!#^XS8+SMq#p>D?J-2de!rD>+fLG*b5|r?#C=9V4%^c zG9TT?MfiDNKre}JxoBN$AQVboM!(bMo-xZVZgDW4fX=JH(?QA3T9<{9(9F*UgfgAR zwzOS8TLI^``(~Y5t}>8Gj--XlnOv`=|Mo1O!vj3HTNaHofPMPkA*E;pl+EOvh%+VZMHKY)vvpYa}UL9-7li<3(LA8lG79|#i z8(E3TocGq#5TeM~HBIbd($5L|~L!UJzcdubM_A+B?CaKU3!HDv* zYI6^MeQ_6mfA~?6WSI%5^N<+a}Xc=BwSSAJ(1~;pFX> z`cJpQ+2LDvN4iP&jX9hv>4PwW9>zuPcj&Yp1e6~!DK!ZB9V`amQq-}xWI^s<=$|%S zsCB^nQ33@L4H$~%wZbG(sGXTfJl1c;<*xM#701WU88QC>n2d6&SVO0X@3UU5M}A4>NA#{^mR|`En2Sb1?bdE^3&jV{65juZ=@rQiyoWYJz^E1`-pI z96X6m1n>zfS>Yj?sq0H@LUudYV>CL(I$R37z6wI2UhV6PU8t@5wCFH&Du_w;`CF7K zbBd8P4WC{>pEiuGVPE07b1{E@?(xmd)bHvZF_enVqYh+t+o{a`R#RSp zlr$z0X=1lqH-SW+1>K0f^JRDxL9@2^?45O;I)u=Bzc*1j--rJl5$0>Rls~E39!&bvEQwf6%5Cuf)KD>F*7x--_K~u`C zdwEl106|IB@odbltquvrzb5ag1QxgKh@AX=!M-^2(D^&Q`3mC^Wunk;NjgkW&Dl<} zaoX^DSrxWzdRD^%e2lca)o$G!&Jwd;reRf8^;Pa)?GfjkF@m}!7A$LGj#sV(wZ&W{ zBq=M#3;KL-q8~#VTUXrp_6al*_E}WrN#n z51$#tSLlw~aG!pf?V1Fv1D``eTM^e-#aLU=`-HmGLUGB|u;2?$0aoKsZ@Y4krYSUw za$SuD!RO@dq~Sz??a0GO7L^+kc3M)uObG;pi zkcuWCMCkHQ^Tdu;qpLv#fgV`T)DExK(vU84Q`5ww*TQk^heTWpV#uYTs^~+{E^hS3 z4$8{-i5tNtMOrHIT%4Pb>pz7siiAZbs9;f|=7K|)dsfUz*Kt~h?Z_irve~mpcWDK6Jt@Q?;OsT$9#EAca~0;|3PI&AN1_oK|IBG41T)L&vZ^ zBM+A?UUmt>3l1$4_34M0)%N;+8r4@M(zn&Q`FBq!feol)420W(R)ZZwl)R7~-@f%9 za&I6<>0q&GWV93x1MWlO6=wrvw z4_|ceLEb>eSs+gM@;e2mPX-m{-^P&LCdHb?scmXou!H%C#`ba_aW0+{08TiI$)v*B1#ut*GwS=5!Ruj!wMsu!yi5I zI0W_rh@ecAi!W1TN8Uw=ha2!~_`~*lyVeHC6L)Z8>Pf*`fP)N?*BU{NC5L4&AIV_} z;m(ZO|2#m%;OQEW&Sy6-FF=n>*=7U|JgIXy;n?={sto=7dF^S}+-6vrPaVh28M|1_ z__rHY7whRMHG;Fj6W6)4^Zax^?>$$@^qBjvU1*?ry`&bxJ(^BJ1R0ckKmJDj&G(O# zjSU#xfr@j?7@7p_#~<$U*tl3Lrh2tbZ^~sRSO;raW(;ZxdHpN^ zAX=U!OwJT{pFgIn$uZ$Dtf}0PcL1jI@W~aGF;h#qeo4ouI15zYB%{?{s|RP}jup)I zGcS@;%TPmqR}>T>@@({WDqt;)ru0WEvfL|JN4;;t*e3~79#ay(3NOlI`<|v_wdy4B z+<{U~SCd#P7J{6g%XMwO^NrTVcd86k1=YLZtWmt19)BR|0d5y`GX8~z@lWQ@e_O*~ z`KN~QzkIF#M%U)QMYs5;*Y+Q}1vArM1mOSqyfpJ4TgMmGN1`^WxyxgjbO|77B%%uu zM)gXT2*CXyfrP}tDCu9sM^fG17fN*$8gb0xxYTSP8Y_w=(?3NzU7SCU*Y{obOBrmo zJ3We~-5Ocu%H<6Y@T$x8dGIrA%#R;& z&!&`ldy}O@TWJNGLqF5BXr|~nr)dvc3+udJ`y^XC#4CdjgU|yBE2#l1(h^9zV$`f- zg#_;e90%%$=H9yzj!l0`@)T*gly?l3n9WrUXIqEOmDf=$+N$W|+7z#xjHmD@cv&+{ zm+syKo0t>WU8m1`g9o{>%?5r+CBQjFfaFzX&<@M#`RXO7e#5J`Tc zmb>=*3z@A)Hs0;$W&Qr0-T22tvl##3hOw(|CVd#g4e^~ zl4|Yj3MEO>axHgH&88wQ7Zqgzrnd5Cmllx%Nr&5C(PVKjnYeWe3pZ5-M23T$gaDPu zVF*~!O{f(B&ht~h3Ffmw-lTvpF>80K*W+!g$Ri^%Ps*?CzEvu@wdI?e0=u~)ITH|YM?e=MtpS89qq|yV((UUy5 zVk?p`BXkx=+H*7mWpB0eyB#o}GkE>+3ul&pP>Ecwq~ociTm{kfL~& zJVBSticoca@Q=7H2#?X~R9_-Ira>3w-Gprma-1wZlGTRfQbxw&!}t2RU^tZ zAGHvoBTQjZFi~&-!W1DY0@~7QzDBYtg`+FnyX#=fHlLEk)1+h3Wxvgh8AZg9X6zIc z(;-8$(}yP_*8LGNPV32T#-3`PUcx0P?OqJDrkM8>_yc$E8!yp0)%D8Ig(eyGA7ZU|os%LkLR- zV~93=DN@#u2&N3UoNs`^FjTAxi(bwLBVE#GPvy`$_hOd7|)#`|R zTzWMVNR>*ZoUP(P4CN-L)YtnRdoK3`QWk+tN17qi9O< zE5CUne)7J;z4&fv|7!{lkI$#oQ*5z)Bx7O+9UYJM`|Dzkca9G+1ube|*H!EN8~+&n z1PMS4n^j5^e=l$WiQrWlW8zL!KHsKJbncCsLAtVi!nQfXUD>2F!~_Dqgq`vRuL z%3fQj5Z_SQ4z<0BA|+`z4fz(7uijjhbS}B_rVfAYu8}Cpi{9e%V8eO8HtWM zL(#OAz8=z}LmN}@>M@`)+*;2TDphhtxmy-AG5U@c&f{?|*V=>%r>K#_dj6fxRk7nL z%U(l%#3_Nm?Wn8xius*PXgcR8%RWusU=F0|o{I>gxL>7NYMJPsGu`LrXd2K+SLnUL}dUNWKZ=unjYL>8e`M6bT@@fW5`dScsasvROylj;}X z!LK;*tWxF(pOt4u2;p+IUri-bH-wZ2t)WQ{vRtIFz*}&sMl|1|!*%(FH?ZE<5M#N3 zK?u0vnMK2N9^wxO{tB)<$r-TFC=$iwRkd@q5|>y~s#l>YEgAN~*rb)~PF& zfsTWJI{v630BHuH&yCay+r+dJz3Js0DCOjyjfw%2`Mf_4R3K9@Kc;P5b{uNR24KN_H@f(KVV_Ht z5KUVKJOO0Hj=ZF+1>H5yE82O-1~hVq77JZp@wb`{v^A$94Rz&Vyt;s~=NLiEMR z@66`7IX)kjVL-%;@Gp+=XJQv&^l{($r(JV(%lbzg3W04sV;&R5tRasC%TONqMf9f6JKZkWr5n~9 zVGv}~=JhK}ob!t+5ZU0ZwyCdx1G*T_kKK!~hU)4x?qj__E{{bNGc@)(MC#JX^|o9c z>S08`53>-v?)r8gO-os5F6(8sH)9gN;x!p!R^8FSt68a8?0e&^(3p***IjX-Q$z3W zlUfkS;OQZnt=rMj&qiABpx9YYS<_93DpoOz8f=qs=VxCtaM*Du$;i&T z)o;w)y#=7ztKpCkI+qEf>tle7RoX zp4{KfaU(lac;rQDes zXUjP}2OxotL5IOt}P^umPG`-3f&=kBN= znjw@F>P?glR4Pky@9|D`8%#iXgoP$24eo|vNOiJDyHkCi;N9^3j=B-+ni|p03{u18 zE)T7BvRMOVPcRk&*0c;)Qo}BbV~qI4iHAfK}K;yvC!Nv7qa@@7a*i}n?qhJ~NtK}J| z&fE@drYJb4?v(?)r~=CBkJf&v&m^LqsH;9`Jw-r@HsjA3A>8)faP{6kY)mELd)ffr z^{c?mO^gYBTN}PSH<-!%<|Og&m`YDZMvZUW;T#GIzB#c<3dRR{+nZ|ZG8m&qIhIdy z%U@)T&PAj6luXaH%Tg$Y)K%+86lXi`ydK9*B zh#joSEU;ikC05!y0`}a$A_u^t1(I&+87t&Zb@SQp!`K<}Z?T8bRTG%9;2Q-w?HDnb@rQ3}^s^SF6sZpd~iiryfhblQs zD!uItw$}?hm%ur49-4CK#0I=AE)X+>y|RdYMS;sBX&k%~`B)hX7g~HowPx5lt(YV1 zp%aMvD=8H-ht0LIE|89evG#=|4>p~TA=Av!_N(ryH~XIr+F3d^JX(!k?)DZjl)r_& z)@$wkX(BTuOOPYFzBR;EZBx||?Nf8jqHAt@H7gk4+{GHk^~_WFxJDm@yNcH_LQTdd z2vTw{=d5rP#7Z4-7ny>3g4@YijK%wt@!9en0qYZaCL#f}E&$`}sx?qk|3}sq-V22| zeA;HE#}gZV9+JrSi0`O_CYda#e1gRQhuf>o&K3pfp}T zaXYI2%qf<5ZdC9a3CmU3c@u)zRIeY%Zu%YH5*XIHas_vSPqS}Iw$EjEu|V#9)Po&2 z?|o#i;*p25Mn00&^%}Fp9#3>Yo)Lq@-UzURsZ;sQT#Oxnwa4`7yrEa4JSS9os~Rsb zCyFJdCR+iy0iLnif~{fu1;C_`EMVL44}U2S)JgCqN@b;)0Bw8l@XsON_&F4cOG%iF zSi#!VRnDo8)Pt=xEq7>mSm%L%G>AE)3bUQoaW2nE zp%jjFD#;&*W;fsajGM}f_^FAh;*09_<{ry~2>iA9hRTF!8=6Xj!X>Mv>s1@o8dK4& z=!rw9SzlBgkZ+-kqZvA=uZixfC&j81v}d;v(cf5)rD-08CBu$72cxCj<`Z4B9+G9r zl57k!73vfl9+yG$O)FWB4BVfn`?`V-Ga&?~KT%5(?q-Ywf2dTiXfY_@%m|eeppo0{ zXI$QD5gWAH#V7z#rTt*oh6!w2=Ed2at|r5QC^az#qU;l@FyS}CehUE)6jJGO!)hhs z_(QuuH-9Gu<;fe121JBsOM1({x|b=iJt!qVf7luZ-O+I#aL-iFGg+S z=8rE;>@h #ry#vqx`@8E}7AewVB0>uOR&H1p+O`yrR5B(zIFh?~wxIWc02EE665 zO1;C6!DU<;8<+20IW3(bVmXxcHN5_mlU2U2fE&A6Tr(CZ;j?p*2aC)mvz9!c(sk1V z2#_rZW&1CLp?@Mx|J%Y4>pz8|f6z|<@7yhn|Jxe#{}a*kZxM<91DW$5DiI?S(|<*0 z&-}+dFK+IS{;cdgfr+qWec_)L{tn1?9;c0=Y!~~GcLZ`Y>kC4uVB(RxulEeh@%oJL zXh$$BMb9)hcI@eg({q>CvyzG(?>8q{+)j^|y?6B1TRnRMf{=)cn4jK1j(7SF_AF_x z`1*`J7;gO!odBdv^iv?Dnp!XkV1;5oKSL!Fu=D8I{lzOyNbrPoNOk^W=lyRySz9I0 zuz1d87oN+VfG+nr5gB7cQ??L$=KxaI`j{y5x%e~lWC)Q0h+t<=a9z`T?DB-sV|#3- z^@~wpE|--HX;@q@*Ww&!{jk_kvQbnx;+D8GwKbGw=&Y-SdDuTvpR~F5L?!t}RI2Z- zN*pxLbY&rAG^0Rt+x_0CpGU#dHLqQN#OB|)`;+@^VtQI{b5;Qx8hcOt@5srxz<#l# zP+Y2+HESj8sS}k#Z~Dl7+rWvCe7J)6aU{f{Fb0mXTzi)%^0|oRCGfQu)D&zL-?;184dyrtc8|uMf z*Zktu*$%ss8wnG?edUO;GC%OKRmCBzA-;gbl9{yK0)rEld)__F*sdkymBsEYl!uI;*0_#=NO)tyz_uF7&tARn# zD9CkE4%&B^uxD`Do%k5b@#*}r;`870e_qtY2qW$l^lDtYQb@T?cf4j%sRgU)Wv!Ch zG;>^oo$qpmb@`RvIcsdWbFXep3qyzqN_j4jxMY2T2$#cqQ8_(b?wyAhMt|#}tGI&O zzn4Fx#l+8)_bcL-cx2Qpwi56HAV0I0I(mG8jPXvx9mMXzq(m)^F z^8D!eGCL!9sPD7x`1BWXrQXD|MYcO6-7;YCiz2R}^}w-4>jsx!r6yz&by%A1!9`&Qf}SDs_>c-(-My}~g_skZSYPlEpdH$CU+ zK}qu4wy*?9DW)*C)8%K^F-Mj2B0bhBPM!{QS9Y3I*HC8V%}~ty__1B<>;_J-n&XJW zr?6?&{1aqVQSe0DmIVFq`-70a521~>_elN$jq1K3sEH7R*6|hjC&I*zd>@|CD8j-uq zQYhgbCXM?T#|T_-vf*-XdmNvI!OqoDIiG{bln}p@!BOFRbe@*{c0#N`jtZOv;pgoZ zjU;Na{#J}rtVwBtyF|hL-uqL@8jt)s=@~^&-K|+o>ki$9S?-8oESWBUw|yxQ>nqBW zQAtTJem?Mm3@{3)wE%WV@UxPBIy3`jULhBjCT6-NJ$~IfP)0oDk=qUP)5OL8jQPXE z*ho8B7P5yOuB?PKF^%lGgZ6zAl7S0~2q1Go%9zmz$_gxwQ3T%g@vXtM1oimd)vXYU zetOI#=`Q1?{J-)}U>pLBR(pUn8#|YaSIKh!I142v?}MV&K?uS2Hh;D>=}yB0j_i6p z^Q}A#*!bb>lwrF=k<)Teb3zeamBa)fE1b}ViYH0z3s*=Edp9Z$YdN6tG;{*%P;Ii8 z!yNmf(_n$*J$N6oKk0c@RzTW>eeR)!qrOeYg5a%s`M0U&S+HxtDd zB;GxZRj!l9Gp68|fmvroG)Qd(OquZ3?N{*ag%A-s+P_Bcx!m z0@+c@2DfH`v!MR4F08cJONLiKeGF%OQ6yb0pa7$}GsXGbJVjILo!NDq3OwnJ@=cd2 zdf7JgoA-h4xkFSIsrH{ypG6x-oqT&N^EIqbqu(JR8tGfKZpMZ-gxxtPTvi9AI^#R=)H^cNX4SFXeT%*^Sr<(?%Qzs%g?&SrTKo;gP>n9(00*vuQa;_AZ2*;7fuj`H(nK|dJS@Bx&pe`B~3}l9Qud7-hLS^?d4r2T4HVirOAiT{t zHO3z^41gO@#5K}m$=S#Sq4R`QU_?Yhe!-@|P$QoetcUW#mfo;}TOn7J^ydN3b;qDp zWrQ4BW#aA5)7a>TO9PuQ+O-mo=!@LYid|V8XF%Q{Y56q?<(VHIBN%&vQ&nwmE=m)% zX)w6k6H3HcJ{%8k6HF%Q8$oKlD}v?DdBwNBD)EZduQ zo=6R{@gxHrh{;g)d6*&Zl)kDpjMTzZY3igU;X|Vp6sbF`%NdO6rs565YAv4t0}%Yb-ADdS zX8j9y`CkE&e`7%ZM;pffmj(0x&3gRb{pG)>kNi(u7{qT`p zF7xkl#lJ3_e?^m4BcHt5Tme*}`|zTr15lx!W_+%?f_i@)_VMVk zZ!PC?tD}J~hjuzm?`Fq``)BYs2$d{x#p>AF%}(xCmS<*G=9G!Q1gmB?h(9!e5NpOj z^cv4+t@=n|?+rXQqk@^6fvW3#8PUB7S%20 z9JaPA*1){RX!<(xe?Wj@>xmBugNfkkKA@mRiS&FAN8-sOMGHRB6Y;Oc@;>;Arpr7Q4wb7#h54Or#8igD7KIT-i=9Pf3o1u@AO?)Xpup2Vs9i+qq5 zS&45B;a?;d)PeWq!So-rJJ&|HN?+UXN(-C{L(bU2vI{S)x_ILH&cwK9!VYEquj)`g z&))NzDY(?FkFxs42>kpkE};J53Ix$q^v{cP(ZX~%#@rH53&O(*^1QMX97z3*zX53< ztI>p^W`T0dX~g{F;gHGeqm^v#0Gs%|u_0WYi4n|E@03J@kn-bQdg{u_p}NT~bQHab zx6L4%XrlJxDlX~D7v8f0qa7we&s$@aMh4^^PtRRbNrBaSPTOVXWE9|_`B>ck6EN!zrMVhls)xeB2t6@CJ4IK36s01rC+r7hjrMdPR4oY_|+5EN;=`muEUR z;S*ODem4*AczO%v#Iw5S(I$#0)R+UYIqjAu7uIf@e_hy~_~b6tp*!-;>WrqtKHESe z$xqePf-9|32nxt1)@2IQVszWRqn>`gT;43thp_~q?0VCS0FdxT+yyv$1Ez=>(S3rj zp6njTG%T6s!71t-|?={KUL_WxC+=hOrxoMRPJpw;Sc*0{AaK!n{iCIIDBCvjOn4&DI5pCoPk)#8yOSboSx^WX;;^0XcN4!prp?O;uod3MS(336^P0{OavKj z#lHJ3Qdf8e#)$Dj%UJ^re1aFS!RuvUs)s1qSc@_6j!hkgwyqcN-#O@kznfPp$QaC{ zhS1PGL`oTMHaTKOoI!}jQOS5UY~mp#gj49Q-LMJgZx?SLQ8Hacfsl7=n!S=*KHNC$ zPM@2xPkVMZW(Rx396Mmyr>$`Xde2ZP453FWh^4aQuE;{N9knD^BdtS(5fFA!-SkK2 zpwMs7rlw9A-3iaP5P|#UE{?`75vFx8VgL#s{x6cKd68(PX;E;XPocTcMtk7|H)~ce z;`d!Lkkk45hxwv#zJmF0f+5rxMSZCUzBuH=OV~J8g1tS$xsn8D4j6chP37N+rsuJJ z%9O78A{MZ`!m>-$R)-?2AS3i@8k&B}D!j*Q_3jvG^U(lWb;U`n=k6IWhK1S-76Y{^ zgRG^$bloEurc-D&Xc7e@KJsMx2`bCRr(60uNUd2Qn(kn&3^R!sXvuQBVON+qM3tEV zP`0FCFK*2YNhCwgLu%O%EsPYM$wmYwDQ~a=IACvSXfX1){7ki&n>&r@qeXr7l{@0? zY~jOANqr4u5y}CuW^rG;H=n_XMOS zZqewHcA7veZ~0j`sE3f+>-klAMYK{khgwa~ct3(($4=2R!rf#gf}mHJ9Kj0;jN___F@kSrT|Y;7I&_}rq%>@iGZ^zL%`d~M#F z3@+y*PHX1VL(VLf+0!fglV7`~HFkAxpPj5;^7F<6&|F<3u2Z=^xV@geI1_i%>N&fs z<1#Q0T~DiLS>vW;&m@b>hA>bCuSbZBg@?DU=qs zAZK)p!;!I_h#C6?e8!oNH6WXu&G~7YwCGKCc2%(GPg#ET9zJB7;Uhes@Mam=z}mEI zli)MrnCj}E+MK{5!`Yv(Tf>wr9AFJE=7I`w>Go#WtZ9t+s~Rq%cMIuet)qMdG8>bWhF8`=v&@z0al0<7sAbg9v^-Olj60E~(@Q zpbMOI2XQ_>ZFxHnor&#P2>_mw^36^UL5fyNJ&N^0TmF~~-%dLA+u$z(4WT2)oz@}l4 z${s7kLW)zn|0sYL3!1D&|H1<5Jm>(FMGh)C-T+)aZGY)RCus1QQ}#i_&DZ}C zJ8_qIud?Elb~&^S9HN#lm<;q!6ble`D3bm7#<|aJvm~PSlfLbZ>8()|qAIZ8F|?f%k5X5b0vMGRPS7<#)3_iF zWu4u}LlbhlNg)-ha{)vB*xjgoec#=#qnrYf5O@t2J*!HSGc)^|0TtRlQm%90QuV3l zhbN@V9upRWrsiuS6!;;3)zRxY$)gs`48D7xlGn(+2{zMJ@NEVdr|wV6E#;^HexRT3 z-f3S#7*@|N6DtH(zRJNh?rYaoVlr?TX&`VQ1!NZH@va1Ldi!+@&8}7w>!Vqa_&Dxt z;BC4G(4GL@6HLH4ra4W{VUr`YJh#Yeet3ITnN3O+E^O%Kp-qd7j*vUVDCjqloQ4YM zpyAwF8YgTWc?1D+W@lrn;AhV~y6HI2kvH3;c6IY=fUxUKT+ZDz*F$`NJcKrh+#R~e zkN1q&x7P3ck%iIOn!m@HX*R@q|7!5~AMjMz|HI(%Zvd+NdnSzkL{VX4qW`ZZj7wF^ zm>aS<69}s! zB27@8SaByhxB(ql(5YMaz))kTZ;?MA)?an`c}Q9x{I9L6?e=_i>X$A9KoQgsHrfF!bzf=l z4Z{UYCBDyJjX?uMo&hFJ%V2{O-!jtigTyn~rI*GaswpbagUw}1f)!i{Wp#q#h$cV+ zu=LyK{i^bq-Ofb+!G`g#0U(Ry(cPYR#y$63t%x}Jqj$`hRF>&YUB%}e+Ga`LE&4TnM>I6F)n<#tb{f-E%bQXQ;1@5g%lU}M69uE6rYp=zU)hFf; zPGCX;G_~ODL>&$V7BlattWyCe+c~{GJ+y=(`KK8Ut*l7>4huCpqU{5luj=fe&!F_C zH2}V8d+by3c5M(evvrCs5&JUcOi`ZrDt8-gB)fYA*^}RKbtw@hFpI0>E0=y0p=fbR zHS=<>R{S0VD4x2X@JE&McYIK6ypw-8Ts#*LaBJ>?{!(>REPN$U_<_?pz)c6x0UOTYy- zCNwKAi8o+94i_Qtj_?4~MboeqrW1*OwQ#WPUJ;jD>#otF!60=svZ*Z@_LHfw2K74; zfsoI>+WvAcbPoV`ZGy1G(}zfJ6&_%#D=f}98X)>Bv>=K)!T8B?r~`yNYne_ZOd$Tr zVlFbPPJ}7RJerWRKpZX6sLLF)$33ZU0No^rc!*cBpxDvrDcy2kDoekF_ z2jPRiv3H>9?@``Z|Dy?C4f?4x7I1I&mS8-AfqP_r5(7Nh$Op@1@&er;)(Hf{Ay&tH z9kP8=1yO}S)fSB@Gtl2u6l+Suf}?5>WWAr?~`H}lMpTKdUa-GNR3_IL_8EK7jKNKS>XjndS#(trh22gnX3>34Q%pEK!$or2V~2LnCPX)f1BV08|^#J`=}S zvH*hJ=pi_5wlW+^n4$FS)O}R{ie3g!9G|qw@Us62;Z8ct(7s3-ha->S{_VOz4~-Z) zvN{=wAW&O;0GjP9c-&wmV?gRk2-Akyp<%n;hJASltr8t-;a*F_r|v-d6BA z?6IQhLmS!vnWwHib{6}gLRBV@Em}D+3t7GxW2-X@jvINw9QO$H(G~aE%o|+HTkK|3 zFB&HLi?_U+Ac-oH!!+5mG()tG{I-l0c!Z+PQ=x@8NUbH&9hcLkSYD;2`W@4-b4ylE znRn_1dq1SS0cLHVSARkuL%mP!jNbY>b2dXcEQo4@L>YpJPSRdQYP`Woy8%+>IFJk? z*LrU;1^s1nu9VyV@qud5i@-s(>|vG*dtyHIz=I?WBfIcoj_zz;Y9)VjQ9wfoO8-p5 z++pu~i}HKT*_DXXF(w2vs*uZLY@Ru9J#B(&ffgqHEn%8FMP3%EB*> z(#oj6S>%GbyvxhD^dyNMpOWl3{O?C_i*9TFzmmAl>9^*%x$2xTbPkF&2TO2W(QGH^8lz(kxe43|a9bQwU~A@0tlkJXZb&r&FF)qJXZP(gMZ`&=3%gIv zm-K1CUfa=hmqeJd0>mTWEu3`VMICT%Tt5~-h75pmSpqkd1HL+nXK_4^D$Y2H8~-fB z)84OQl!`SZobBizZb+luNSAt?F%Ku*1lRQ7Ls-xgVEK;R4@>Aa!!RK_NeL--9bohZ zwwNbiTimyG&6*WTsO3OVjB!w;kna?6E6VdvPVZ}xx=JGMZhbr=L**lqmd3S$;2pK;)W}49Y_`L4txmqHK4TVgD zyF#6ByI+Xck}svaYsEpfC{k53oq@MpA}E0b`ue%H9Rk<#S}Cr*4%}%D-1bfuqS0iT z=YHTmJZ*`POIJ^q+I@y4(j|~*^hXAu#Z0C_*I{`d7vuLY29pbNw8MRq*g|!K(A0PH zN+~>3jb5-=JsW%kte`8UZ(1w zW2G^Zz2o#z+J0dsLk-N2Fu+8}S{&hleApsTyK8wBoL?Wk-Q%R}I@;UFSyk@YcQ;DM zB1y-h4>Xu2n{wq(`Mxjp@!9bPe~Gs|nTJIj!WM4~!mCRL=2hEvcUAZ&tve5E9Wvil zs>(dl>?JxTtkIkbDbCMt{)U&`@FrA87&mX%pQn+p!Y&D`L=9boGSc~_X?ujp?{*Ry zSa#kM94@~zb9TSwm3YtG*))i(nl|Sa8V_Fy(~k8*QcA6 zRb8y1%r@y+iF{Wt!Eh&IVt!;m3|2FZ@?7TTl+<7o>4xvMSt;u^InN}RsQgOA)RnJ4f;8B0(4W$VP>V%y?Rp#p!&pTSii*aFUQ@G5^3^tv=jJi zcOc{gg#@PVqF>TZLWxJj9qZ6{W&kSnNnVE}+#OhJC8XP8>Bl0^AO5GXr0!C{Yb|ks zbd~9_hikU^PK=2wxg1JuFn>TuXhSiL3mM9umRAlM#`jbD(kPSPxDG6Q84#+-GLBK{ z@ABkVqxihcCcREw>@*WT1xR{izew6PJHD@lwGoYb&dpLxgkEwEcf^;^JjlpPHsp%& z6qYXt$MV!8y+{mJgoNpYKaunRR??|6|JCgGKOpmP{D;}^-+<=%_so9(nZd)#@n5B) zUjDshI~Ya$yIp!DLRG`Acf+${U0quv#+n3)z#*Ws*Rvy*RLRYQiLd8*dtWR&w~1#Y znK>eW$OWGu?&z@5cK*Fov9k!z*XjQAP-Cl{>-~8*wUM)=oXe`3w_aYM>hs1wbG4K) zv{W%fD3_;ES##`%2cn;cCKXgdt`Z@}S%Fps1^oE~-$nDw{SH_r#?OrsC}~cydTD=Q ziLVQ*s(^3mSpV=V4%d)HiibtDM|sMfFM~|y!5j@tr(*nxD@&oPijsq{KU+Xr`5p3H^f24E_ye@!o)koteZz~5c)DO#II#>Hji_c$+_LNQK zHl`S5jUMi!bzZQzty9hcf272ROm%8JpY8OmGQKSD*pSCIMHu77r-k^W7x!sE&+vS_ zK5TS^EA7X&z4q~AfAG{Ti*U<}w*)yl3Z5+wewu^&6?G^zL_Pn;>p1}*WW+?SBWRYeDceTgv47 zc!EI{*}1O8inyXSTKn+emHTtdf8Z!O*8+~#=>+YXgpBa)i@Lgw@laDT&B9dej?$&1 zdD)k=F)%9&(JHFmm-VZpPOLhi0CQu#KZv`02v7QQG~Trz37OoT(6-4BfkB!pWIs*_ zL5OeJ0@_$9$p})gi6!LxAXS;^N+Qxyyli*i9uALpABKz+u39~#4TuJP*u_|>oW`?M z^>uLnsBW0@ewXPh&d{#NMJ*o-SmB9YZyl7{0We{AXMRTCG;?h?wF79?a|W)VidHzs zmnM_8>#0kHw>NGVVJSe4yH)zj3dxO26o9jAVY^VS(LPgvE+Tg)vdZGsk|W`qWJ zG!sIrFCv+8v=3-($VPq^tuUQUg~ZkRRU9iy_VD@^IT^m^rrhL&)opEFu;sno$yF&6B zHuhGLW+|f|L6W1bd2{*nfWOjEZ|V#gX&x+0Cdb-Etd7L*NxwzWcp)(d)!n~XlsGCJ zfim(MSu5U?Cxuu9h&F7-LBc&if%H4}@cg97NEP@XB)HMZKQ-(TFInA!Rn zpTrv=_IP9aiQ)8sTZcSbF!x?IYog&rn`K_Wr%x zhI($xA0V!Dv0QQGd3R3r(LPZ_AvjihQUO93g3|lq8&eDrpG2L)tPepMl)`IuSee*@ z(W)J*p$TDuoI-ri($?xusst31IUh}@(Rmt!J_bD`xx+zA$)hCg2viq2BnlbEl>&P9 zUIG2%{?%Yvn9??}f+6}w(&ZCH$!gklBJk|&Ewz{LR!Mc0jPCB)-08-YqP#N5S-5TEi@~)PWlbq zD(fFJ;wYt@O$;QUL7MSa;HOzYv?16#d^=4Ftg?+Do;2VqhOE!kZX})RE`mR8Zr^DG z2D#$NfPkJ%Y6x|+f?pRPRyqiWD3Yc4vNLVhr+y$>2STJ_CRS%hA5T(j#>g-{b*+Yf zdb2MiKK1pNvf*JSh^1O`UZmAA)*0ofko$BX_}GREm9V!3gn!<2Kku+mBQERB0{9ThFv zOp)xc*SszCN&B4Aj6p_77;g_h!h-6;A^&kj1$AG-*&AexoV=mVtg(qB2nTv2&d)=w z7w?mG#Bzq?C0$nhp3)ekThAI+dd(KdE>LdE%x&%)MW=DhgWk#6=ri$Gv8WzILs+}g z)pR3y)rT6ZSbM{b0kXZw$WIb=5kP$71qgzAOXoj-(6+>`sl~0;KWzzm=!ttU(zMu1 z+iiuu$96OflRg2HHK7a3RU$XjK-g>}P42!YM;Lp@TIA)BxVS32wL=U(wlk)V202)c zfNGLMda0{V(Mxag^K1dpyx=>ovT+b^oBZTJAXYECaspXv;H7JK z^F0fZd>GJj2^QQqdN`_Sw!ELVIS_xPS7U0g$?BNdL!*JP=eWtIcI@6#xcROEcnGc{ zDz29ie2yU{MY+_*+A3atYgn36vXmI#_WR&Km ztU!netofLttt~zMEdo@zEUt$6A*?=V{k~{yCovrTfsOWQ6n{b^fFO}3<_(Y2gJgbJj0V3-GB2Kb$(OR>U(*}b)cF{{i+Mr9_Yg0j&u>H*H zJ~ZluhBdM3DT$fHahrr9EJ4|a1l{ZsnTggE^C6|-N%{GN-0lXHT3Zh$qV)N?NWK*| zX^W3NVPq+t&ufM5K!x;cJINayeAEY&b8iW;_8aJJ?QlBlz3~F;c)cKXMY63bDno`KU2m#>LVJY{)Rzt@N_&uFIZ$lMGoeE@+zqgBw)@OL!FUV6dJwu3hHre%Zm(R-Dl*x%=D&Wpej zT+LBK&$mbVDoXg@5~kOlQWH=iih%Th1N>CceZgVa4!I-HbtRoPrip*bD6J{Idpzb( zo4UG@1YnwDcKHBsE|4>E$sZi;ZTw=5UFmb`KR>21(X{&{Cnl8htyq^aONIo{#!SFf z|Ch5!nwg3Way9cM2ml2Yky^+n$SSVr6BjOBrj@A} zqQBWIo5n)F1aS0aR+hlmxqnC4Wy?R}JFAts4V0^}N!Gm#+mnY7_;N{0&Q6Y!rC}F& zu(nQ=bZUrLwZu@%-AHf|8q$23bmE!m5)hyPW7P}Wes~fiwF!V*usv;cK13%yQFSD z|7K`npRf=_`&hqTmvdRGgax&Qp)DACc*^=O^W^5#=ZSJxZOLR#n`KH!tEe3y`k39iI8677A1wy%%a8n##AE z9)N2e`!?sL7;7Ycn%vs2qfd-snO-_mcj`C`N7*(uhk7yw2adcFnHEgb6L}t~k9kUR zUSdTfU0(ssMJ}4ro6L`Dwb`74(txwIz2x!C#5vNyCgRrhkq73icq`q`XYvSWg01Ku zFsMu(?R?!;X0ri;s(H3}F&12-hM&X3V9TD5v^{_$8 zEtzZ0fF`SFAaBdpfLhWj=HVC@r^O|7_+yKw1jY zPr&iTQZdZYv;RJ#1-&_bImIKJF-vNxMiYQfoUwwMO!b2h2dOt$tVlm@WV2aj`8=acS3$at?(BLo!xM`bfPDrZ+fug?CTD3YU3&Tk zYuf~!50Is!E2^fJxzN?PiX>^B#G#S<*Yp7YG@P+r$N?!YeKBk0uF>vh2%G_WE*N08 z1p+Rf@ILNJo_QmZUO53&+^1l?o8h^GAvJLBrfdo47H-CBEjnc+3w<$fbLcx~q{_hVKYkdX0n7=)QFKIp zM8-z<(MT%eyB6>gsN%M=YjgL$r}5Edmx}GIWujW0qPUs`4b5qy7XvT90V}_bOswym zi1XYw`jHrRne3WeH!gi85$k(RsMg=aJ!HKfF6X16{dygidedsEv{83N@v%35vySNn zeK0PAzJOPIIuG@o!<3EP7L9}cB$hPO-Ub4vRX?yD5aLU^8JM#M{p3ukDeMM;xq-?a zOlY3SjA~D5rxKMQXWY<1aCMT&Bm;i`d>%}2zNSdgOn_=I`Z1TaQn^!1aJaFe=+9kdmBPnzMvvnZK zC3i6nVJ%j#h_2XoSR;dTW#M~u@Ug12NHIl1Y`HMUJV+k4TVmycAMjD8z2%7BHlTd= z37kfC^DvXy32JuGx6oJiA#GcU_=B=A!)ca0@a_d^; zpKS>*O$epodgeB6Uf z*0A=gTpuQngcAYNz34Oc=5w)!{AMd7QK0BNZy4v%r64X}?$-u| zhP7snb)_`F8F>+Rs|*hg`*|}bla0wW57gMEyX^=9$pN7`m1~9Lh1!eYTDF8wubD8Q zyXm0j{TSnRMH`^~cBaNy1*L6UnD27wS8VJrJZoN=pX_lpa;vyX8c^X|$Pq;oj6e*+ zu%GC_7LOaZca+AXCV>sXTwfy(U3s=pee1P&58*}5&hZ;&rZN?p-Z=Mp#mu* z2wtK4u`KAEAL9Y)Ni}Fn5*VS*$wsa4fp?RWk1QDDu&fFSy8{()W&TErE z9p&K5_mW=XM24t2a#pVgIJdNB?gAP_m&HO8u4-{-lOPQA>M`=v0U8!6SVV(O z@dCl)TLCAIP^%nQ1JO>yAW^}{@0JS^+yb|dw1m7&cgj=zsv^P*jJ@QWF=*SYELzx) z2}Hzo*NZ|45$skjg;nDEtk}2;%ghEa-^H0Tpco}m7E@EgX#*k_W0T^+&Ume1=h^ip zz5v7toRZe2XbTr!WU+AL$a532Vrlg*ejXR5cOPXSZ=o3~mmRScPO8#4KxX{fiGdbP zG;;N&{Ad~KyO4>P9y>v)q~k*hRK$i0DA%4YJzwRP3pLr0Fr&y2juC!R^3!*RpMI7# zM_AwKOb4jbHX!b_1;7wxDEobESv4W(20=7v(tTGJpTQ!NC4~-=APEa#)M-;OC!t{H zH*#-Hq2Jh!3q3zZS|D9V)uN|dbi!-k1Xy{saIV>O$`eyX@yl2ic&E*gxoObp2&57& zu+F7)8%vqmO{`bOtU}A;*;0k=ej$i(6)dO!x1WM0j0hxD;Y~@u!ZOFsWsEV_kqaxe^6mk@!~K%CJPNNpK$$ zi8wf>ob07STIINRL*=trU-%U%Q--bXiegqRS%jF2I;u_@(+b&**Y)-0#vzbGH`-k29a-V24DPFL>n4QEjOMg;2OA!`A~uo><{pACJ>S$COwHvno+MU38Pe8 z*PRVJwQ7)RzhiCOcJ$bycyIVG8TdSrsk#^FGNBI*+9^mbUVNp)9J!$O{EmRcLOI_; z(fV_SA(=fIljYh_I!$i1Poplk7-tv2Jk&o4*DerkuV7AomiHFwjyugRoz$j62;axph|*uaknGFY4O z0t{()QxG6O!!n444x4pYu5q^FiaX=xJ2=;^9t6P1Kw_vgriXQt&OpHVePH57x z7eM3^F)r%XY>2NbM%2r`h+cv}Z5pHd1gYEc0WxN@w`rHozY&hm^p&8n(XU}z7G*FP zVNR2?51LroYD zi#jW!`U9avgec*Pa<-$2zhs{PgZr{h-<&vZfxUZ#zLVoyO;vMHlW3D_d!E#$Su9y_Tyu42VF@7G(_) z5)ejObO;NjzVmqsE0ge>BLfe|7~n^;NGdpC02ApQ3Yc^fWOU?Cr6j$8m5J&1H8S_Rs?5_LgRv@f5n{;e48e)1oNAlEqd-=kb z?xQ#COkCF|Y=WHWZ?Fk1+cux&4oDf9pRnZLL}wIO=Xwgsowb;-WhEb&lRt58@IzFD z$M0dZN-_3Z@AD&!{cI17l$>U=o)7AS5)Qajjql`=?G&h|@N-Y5f$m2$YDmoCYE{P- zGtmUQD3>YD!_c!?bdW4x3}aP&QK}#Hvw30~&muS%AaWI4LipqQ+87bYk>=r z)!?~HS__mUrImc1R$M?J7f?VnI;}7`O`SCdF8D~xmJsa~4pw*Lx;?tzEQ24q{SG-; zSVqGOgY9`*s*+?_MBXo9Md3hbH`DON`=BFjEhw0zbiNE6IQZ2d&HctxAEKz*P324* zd%>56LP~4sscgUp8Q>ZdQy~-QL9U%@=VpwRnxnA~8|y(alr=hkSCVv}bf^dSb{e%3 z&;D>~%fm9@5TkTBVk%~h{V{IMLkDxEnnR2^;YNvx!w3XBXUM+M_p*~lH^he}$D z#C~zx;ca0K=w1z2A#D%ru3W`)&w z9Sk-*WaQaqehuAh>?f7*nHgF!ACwp`I@=rRg|G2!XRYMUkZK*l z_*-=(tLl<~BU1@fLf)aS^=?)>EuxzCP(>7)k@#>w2VnVjAM8510T2vB&?UX{9J-1zs1K_Dm??Zs?{dE4m1PR5T@s+20H) z`dmxfS(89q4LAv^!seMBE~kfCdWw)?I$O^dZa$d6^A>yh(b|w--C4|Ea#pVgmVtB~SWE0Zceb8A5b{KG(J?lxUM=wAO;> z&W^pyR8olTadme2BPZ;Q3oF<_z3V&l^VtFZCbcqU?@0Lo*xp4;=oe zGZ$PV63tSb7Z>O8vN_xwiH9-a*u8P`_NBQ(Dm@3x9cQ#c#pj2(5Ayag6b19owy6nb zH%>amjbwdBcI5R*EI2KlAOY8st6}&0XNJWa`cj+MR$nie|PfZVqgyXJd@EFiCe)LGgDLABW5cwoXHtxUDTnZd0XPf zh1)!oOq2hVXRTa%JlNiqnXee&#x+Zn^@N#zVMzp99B%(Ye;X4qhgHml@etz*u*@e$(cTi%Ie`8m~8Ggh9)nFOE6`2Q3a_*d@(XRdjaXLMl&PR2T_cL(Fo0@J!9}dSN7D1!g$`x(ZABWr z31>58(U6=&?o9efcpofzdBn10+jDrk>bsoI_qMunKp$O&>7Yky*{I1@zi=Df-~&29 zFaVh3`@p~Rh5R?cRDQcUl$;!#4V~om9e(e8W%$b%!btx=+6DVZ?f(^D$RCQ>8dz|1 z)BRgeAcp^HK|;j`Y|73M%v-h|1Kyrx#i5Ra9s8!sgM4B4HfpntJ--rqI1LviHpNs# z!kV5Q@9voRdZW`~1KxHdG3@XbH!k z6I0D*wTlHcwv)zUuf}yf_o{=ZG)>!iL@7Gu6SU>>h01H5mv>3IlVDtJy4<2-HJ{j$ z#AJ=!1v#~Mr-eI07uK^*?Z@mJ&C^4PHLg8Ehq7p&@ct1F>f}x(=7_!)J@V&{a`D5o zHxDmg<+e|mTF=!E;yC!s3--Rr`#u8I^NpMqjh-HT2QX0Qm&Yo5AOFm_4$Ut2_~l{- zrof<*Ln5u77SO#ZFt2VGH#U_cV)O{w%`c&B=ePAvx^(OhUqBT4C~rwZr8e#i8{hc1 zT3k^_Lt&2-+8T1nIjSQ_GJwkuqqQJhpu}K zT^>XmFrvyAwVR;GCkxpw$!5`iB4j5b_-X8YH!3E0Fz&0qfq##ki>(53tM#c0y{1#L zZf=}V6CPgT=krENB6v#D&N`5zEzp|;llgYAU#fmPQlv+B5sKS%nYxkxx1s@8;m3hS zqVq`GjcqPcFCrDm!6sOHsT$t5=Y1k*UV(CRE?_+sE` zv>MAJToN61t*F%cTvJ+(C;_!yjGD^0?pEj8e6+ex83Dn1m1@t9gYmdP;L<6$g>Z{m zV}PSV$aOHXR@$j1wqD}dGQo}ej{s9{RGnj>eQ=OqXmQY0+n`l#Vh6N|^TiWWL=?WM z$TefgpHVbp^%bm?dh1!Y)$L!(e_9bdfqxc;;<$*-L3ON{W@n3LBMGn>yin7oRO)|5~vew6JsXM740Dut%vA^z8GSoR7SlHjK!W-F3IBSlO}VFwry{XBUTiMe0w6uVUxjP8sZmf+ z#%Pv24J^>aE20!Ds1%Twl_>9UBUWjM%)@?Lc)#HovxidAcLsz4$ld6ZamdJzlXH7o zss@EM&UZQqgf0e(ZIx3KZFQ4)!j=-RvRLh=1Q8qbyhI6AyXt*dtzEH!+M@+y5s2w^ zN&<+c)m12x)Wf#e5)l&pai;@iDFWNWpiy}NVu;VP+Wea?!z1yDd|J4Sc3_CgC~Xgc ziEf)R>AdO$LU;oq3mLb;M=LTL9&P5n@hM~LHmo|=@qSD{>s=5xV36o=W_Ot+%gfVS z%=)2Qd&(tju(52cKqkywX_`eTwG=zqlpm6g*d$3%wP~yKg2)ewDA{GKfH!1j$L2r@ zzc%U@N;9T?-cRbsEg|oXk?aYrkA9*|t^&FRaZ%nF=v#J4!B3i?fQ_^euDai&3J8Hd zuTiHJJZLegP>uW?P&xz@SBO>A#rQsDIi)>4C!KF|r#cseA#TJO!MTwUyw+T>T$qP% zU*9(h;=*^qE@z10rO5=RV%l9#^h0B|C=4n;kR{I=Rh$Z{Fpv&Tq4ElhQ&#jV!_qua z8tYO3%PiQv;OBDZg0F!SHetNIyYsRZoCv#w7`1TUy0I)rA+2;10TRmcIYBfTOxW~*GG+tD3);}yRomf zpjPkG_TWsy!7wT+SV*zGOlV_zH@oK23oC5Yb(A|G4v8k_954aLv?5X7kjLO!0y;OLLazf*xwi64% zlW|SYmvn~}-Qy5+kCt|46(B;uSpry1j5EHb_)Iv)>*dK}*eGR=9%n@XW8aZVzp4jf zP95d7g>=d)*5uLsMnlSzO52o`4P#wU_JAs~i+ZIK?@cJpl+`GKyo|j~aXHi?6OF^E z$&+uTekG;m;hw4id(<)~YI4r3q0n+CHU@bmr0vo!`d-?yid4;Q|HBlODiSKMfP#T9 znR#kD&fN%`f+O1`mY0bJW`eAKVvr)qZUc`A92b`zFoyGew@Ma!C6bng{^6J_Dx3Nd zx)mgscawfdn-?z7&#`qpLHlAZY<;AlfSkaG>L68ib5uB8rNXLx+iXD|U7-jaG?H02PB1uV+Wtrkjufq#8@q#@W-O+8R?=~iakudZ z@qF(;zQ>cp%bA?MhG!mZ)fMPUw?|q0s9HLBjmtzgk$yfWfJ_KY+uT2Rb-rfx-WVs0 z38>(PljOlLh1?e_ zf$k#gIni~Io6ieNetjy80g@i}Q~z@+JA(P$wYm+S$`3}I!}QM2r1IzXYEB(6432g% z+Bwu1yn2^U5Z#Qq`C1dyxzxUbP`Tak_DgK^{zzn6{6ZE1HL~D2enVPePN`qXDW|Oz zAWTAUbBsXs5evQw@1$Q#@@cD0g!^?B5+YPjSpd{D^g}toWIf!XI~Zd zRIFN>i08Vz=g|}2y5d4JgLf>_f6>gp5MDUs&E8Xs0xUc$DvaU7ixRU%4M{LT1~j+xhPCI z3XLYeBuub8dOm!6czXPX%g37oCd;_zXJ0mFy(`#!>TTOxbEp&A3GTR&A2p;dcVXcU z1kdJ@I*bor!SAC<`>Oi~cpU-)-gpx2?G`ACE6t9b zxzJJ0*aZ~&1mX~5`6#*4`&m9NlS@$Q^NRDx1AhQ@9HKWIwqIMvc0LD~93v1Mnr3`K z^g3$Rv3j)Yi^#}6{|jX&=Quz{K8oOvt4+plMi{~+THhWE?V-Cs0F3PDK7F4=Ek?>Q z5F>QrE(6b~M`f8Q@lp_|Vz9wwAp_O#*`3kS7>n~bXfkp6Y2_!nwfI@VD?JsKsOAY= z#)xZY*wtg$UcwRL^hRF&S^?WC93+!a|8QU~<#s+(L~m?Yh5?oR0Q_)t(DsF22RKw@?tj(O{c+u2^cd=5MSnXWUOgG$G3dmx1-}ZkJC2@3kKWh-x6L8hHv4*_P zmb(8?n`|&C>Gw2UtSc+A?~V-jolq;+l6|hyk!hagq!kCeS&z)EUj;snHr>nXgtO=U zuINhHy2?*pDYj^J-lxptIB5ooQSEQ{hIw0P9pK&1X9;IoO#ku?>yC49;}zv_tno(k z{=w2Q@!OT_fY(^k40f>=IzLA>-x0~;=2hIJO=4orje{)9<>bw%78wS&Hs|mm6xd7N z0lGuvQ>aNK#Q;B@+lW^0Ap^V#gDuK^bJQ#IIjYs0P=_6UCM&e^LyCcRH9FGa2{KV* zaNeO|7dqL7W!pBs7EjIBTD184eU@-9w!V~G^j6J~#A|zEaM72X5%NSj{QcLa3 zX2EzD;1_NS_vP68#w`WJ(|kmI0K=b^n^W=7QLYe5xezs>IN#_EwW5{tHKTJ5VVLh3 z6X>>Kl9%ha#c7w}O^xyFFN5V-6`VgI0dh>l!=IJ z25c2!zVRb!5OKX+P5&^__N+)X4)Tk(+u-_Ty8jm!l9vK6DQU3p2b(#Q-S1ZWayE&m z8Ts97zV9*XpWpW4cZ(vWnCqiBjscHA;lvMkx+C5Bxi0{x;g!+I_uTn8F9AlW?tNYO z%QNO1KUthZDGZRoCqE==Y7xJ+zvT`} zJ;(;@>XRI6QGE)*m7$bZ#Y9fp6$w0C=YiW#33*SuN#G8gdjWPn7Jw)3A%$SJyoIf- zj+T|`nU3X<;s;=zGW)ZIi_d)%?^22rX~Gw63XQ#%=Ef+R0jA3zcQb4e!i42iPy)$h!qkZT6bNWjzTK{j~gv?Qe0k&CjY1@)%!x1v^agZ?D`@bR)D^)v!{f&cxk>SHJ@OwV~e?{5)TL%N< zKRFowXE0m8-4nm?TK^ZJwHW^eT8oL5?Y~-gF{h?r`?2oA=b?H@>>6`=*MUOed<}4T zZ@G{^mQZ0OL`q+t(7HBOBB0QKtgG{8oH`{@Xv7upc?w*M*wxkLA;Y#at>vZd`D$>~ zwX5B`Qt<9(vRd~&pH|S>6QNX5NBixLh^HB?niVZ2L#BkVv86>lPyqc{-P#3G&c2Kl zu0hpW6D8>JRnj&iSl3^E*3c|xAy0E!sce4#e4FiJC#p-l{Tkst;suj0Tu9%Zm;~P;)#a6#p6W5nB6oc!87`*1DqmAWjOZ&6V%VZ}4 z=uH0Z6orxZhkaXr`$YCg&}|Xq%@s?*>Ve9OtLn>PyM-j@etzxJHC#B2gtOLscRwXy z7$GxZROTIXy;)s=C_tv{EdQSo5^ORMMxyxjKci$z8@cu%2j@7|(?1~(9c995yxe5U8~cgWSQxq9|IE_6<2Tj zXh)Lsus>A1q)+r+)63He1+O7U&6sNbiAvvhdEOz6Jh1vSi}PA&%SM(JcSO6hy1m12 zDr%$*iE|Cgy`mmNwq@Yz^srvdr9TqJNZ|$&}evt-JL5YUXxTi_EvlU{G5*R z;u_?+r=fGV)?z}4q@wLSr1rNo9FWUloFh!c4zk=Cw}hyrojJMs=eP=*@v@DQn0|z7 z4W-DdfgPat-7D~?V_7_rj;ASljve-?QD?k&Y_*2dnG~MBA#lEZHkH|fV1WTsz9ckU zpygfh@WBDop-&U3Rn-*Q(0zG%;-uQNxPH*?aHv$lh+*X4H&OY4TVvUW7 z(}0v9VzM_&;(gx=*9&396>EFV&+Yp>QgG~``Fs!PpX;8tv9M6!p?A(Af_a9SVz5JK zg5tM5>pJU^z`i>i4vY$@A>3Be)F5542FCM{AbF%nT*7Td?!h#Kut+-~bVzU_z9uyE zle@4;NA>tuZ`4kIN`(g{sPJI*`B00L6}Y(R!Az-&l2!ouvdQf&Z)*6=0B z-I~7NiM7(n8zEh|l7>&k2655a7T({W&juh6g$1^%TwUx6zmI%bS}b zOJl(zbTEOM7n-Pgnl0Dy?mm4tKH9K8k^3*`RsQNifna=13&0Z*3qc@j7gzdHDM+VF z-tU%+ex!;4)23rp&+IGrTIAdfLpEZ#a)HVsvm(U>A*98TYm_W^HOeoY; z*Y3wjuWl@uS$F{B;ZHPcEJaHiKL#$x7!ikyFS(DeX+Cs%jht^O5e>)A!|w;ocRhtC z(vN9?S|LG4T^<7q+2jEU;*A~x-z-M!t12!$=IOgFcC)G>yIqH_97Loqs~m5P+*e5L zjit`3dm&b-C5PriYNoob<35ybKQD=RyJUKx?N1f29f2!0CQff%B#F#TET(i~XQ@

3}C~MH- z%LWBB#?B}#Hv~XRTv4ddH~L`XuBCZYK^#>ja)mq?8*+Y#%ON$EoF1L3Spq zF*}N{6MUp$so-Woi#g4VO~QAsS+Hb{_>d8(+-G-u!`e?Y?|V!)Xc3}W(~-XB*ovEB ziJ84VS}5^3;jAmYjw)E4J`~i(haCN-AM#q>ao&7NI{zy(ZnJmOh)?%(r&rhDK`

B`TPc~&xt4{&S(ZSak^l3XAYF&9G_-h&rP zn285yOvauIB7h|&{lLJbRafU*=IBJWR12vtxILxT%f2@`Blrw?o^OmeIf(S(oko#Z zS3S8>jU$<0ZiaRpIcBKvn4p^pNkle0*p0amEtKjKg zGKJKzjR@#L^65mCS({J$c{Rr|@ybqE3IZHzhpne>TwF!{f`Ii7hdn_X*Fw}+3YRPc znmn%^`??#O~psv*;LV4ksqleo8f6IM9c!|_gP0&suB{Nba2L`L$cwA zt31V)dG!yGi}s(b)L6buKE)GZOTsd#IrNzan$-{QqJ(-m$k0+OeAeeqL@vaG5zHpd z>AH1A2DqXWw&Ha>I)dcSJlW>c96yUI{I2<+GyF5oapQuM(p`x%Y2;8oiZ1RYZ+LO96@14tys&Kqset4IF@>*kujNi=@p;lKlBb$Plq4cKMai0(d zuw3FTe9e=gJO9u9hcH^ zv0nBYZkH0oJnx4DGdd5T!TqFyosz_xEW(>!B*!zBWGjQ$60`b`ilAEZ?GxC^DSFT9 zAg4QchNGxbusD#32nA+B^4Fr6PNR`%iUrC%%mXc}g%+1BPW_!y3DjMz%6Nj-6ocq=Qmzg?Z3IN7?ZEh|o?5bE*hUzcS-vfG`L7MjJ6Y z+eH2(rHX1)l4b|OqymDHv+g1%qFq7yl6`2ccO^tskYsOyU#DHeRs4WyX`EPYq^h7G zKUADFAy89mqASG05=0C|1cO7dFHTF*hx)*)=9*ts;f9S;KVqH@Nj4s^%u}8<1ftH8 zmyLb78W;zGoPz}U9O>mF23VXTHDv0MT{sJhy>tG8ecVD5A2>Iw`e<9>HX~Bly$C&( z9qy(ehg(>kTx;fo-Y*c}{li?v0O3q*PF!p_5yd3RD9oOGsvRisJdz+dIkaN33@o%lN6A*W&EzR-(c2mV2cF!nrt-1F+o| z8?NwH(K-Ak_r?2yV_N2EjZ@UOluL^hYot*Bt~xoCID^q{|1)84 z@uFMc^hI%0+NH0A1O9hKUpAQPYe*rb^iKEcpvETBn1l#>8XbQ!Y4@4V=!nEEw}Fs&09@uq>K8W0S-!RMo{-f_kEJNrV%7M*;0T%J-Acn|oRs zkwtqH?1(1iQHsO!Si=tOjoVIL6MOqwOM`4$wpXbxH+(6 zVHnHG&SC)RSdQ~jEgfse7geAXxIAQVl?C$N((C3Hx@q;jofomW+vIdJs{#gYGdC!s ztv~@%^aEt&QeE1o3|=9|s>Fl-bwV;qSz1#02lfGpxdeE|;$nq|CGbTmlLTwtIjFgI z-0K_qkx5vJ;bgEGvts`JOtx+|F92omn zP+oOq)qLYP*>k*x%Y3$xpK+;}!+aY2*@zFS$qXBu?r zQ{fB3U{r%gHt(dAZNDz6zE=L=1i3Mme^`V;BvCD81eTh^v^f4;yQ!JpJEcWjC3)4O zz^-S8M#y;5X=Fpd%2tm26CsCm1nE)%%%mi7@KRjR_t4$EdTB8~NDu7P0<@Dh$9c2{ zp#}zb5;lnD0?9SMQy3Ww^%M)Xr{{#GAd6E)e~}Ko4Q`Jb!DEiRGX#boT=P2 zyfouoA9Mo|b@N0xf@NlypPa59!+xSo@3{l&4nUR)_~e8}w6|Z^^q^9qu84f%T<0?! zMG??iv+%ID&jR1a+kL=(O|8G1eE&C*=Kgl_&Gb)`@BhC*%`yH9)EpZ<{eQ91pE-itlT8+#IORhD>KS&q^@558mDO~lcbVJ`iz#CyW|l=5tD;{ znePnBf#Pz!YAW866qXCO@scu@Wd*qj6+_}WM-B+Wuy}i60$Qpq7Va@usrOaUnGt@v ze~4tO=9n?L86oMwqXTuKLG!!Y_zv|6xh|~RQz#?u4~7Uq3zB^(-93Cl5+Ift)lAm7 z!FJ%`$s?`N$H(2SOswd zI*1ytSdm96DBo3jhB0C{qj+Bl{O6d(ZsFdeG-54SS~VvH&^x|`CKK{bf+CTUD#_@| zE2{gJAa$CGkX10v;ZlypHZe(7U`ktgjQ3o|`wxWEq=7!6nZCG#j7sKukTyBgp6h3=%dM<@wht} zPZMrgGOPXwBk%NO@rOGNS-e#L??&`r_#sM8#@4F%3{32Fq90iFvijD>bOH|M`c^c8 zwpK18Jf|_+B#V4Tm3;&Gd4FhbHe{)+*s+GI^r`i(g_rurakV#;51yg)z1< z`fwD&{NbSc?J-nxHgNh?QQ5)S_-{DiGybxMBAv9pqmz)CzQYF=KRunAxsj8ZqZT9E zuZP%qkI>xuby2kS?;0JcAP{zuNNtiSe?{W^Y?`MbKmXe=zhkW&6R{ayMux8L;N z9R9(DiJjw*^1pQY2koPr4xOOBqwz1>|A+22clgr^9~~-U^ReB_+{X078a4tpj^_V% z{cl$MCwu?39ZvKY5B!f_|7BGnTj!5kg5?kE;xqmkr{Gs_$T>S%ncEmU{u7H|HGX&5 z@5N#GjK7#F(h1-*{m#f5yL~YJlZm;Ll`;9-JAfR33xF|z!$)fVadrj3r}!t9e=SV= ztrgQRD=O0c3;$mx|A(?nzm@$*Q3qp}e>6tH zkHd!!h97b{|GnhDyye1LzgwoRq4^<&nS&MI#@WhBhfax3%vRas zpD6YhJkf_e|D8eU|I^0&H6DbuSU&9j%Wi-60`q^`3xAD(-?t1q`^U{_Y-8$VhR?{v z{C9EN=wv@0sr0{}jB*ARN>0{)ZO?RDK26oJU1dcLeuwny*qG)BA*9Hqk1b?i&0vN# zpu6w6>?c;u`oYOGVAQ_y@{=bKmqm7(Ro}OXd^;jFfB%rA|3Qer6GG>ZB@x>LDw#Q$ z7i@HRg;y8>#v77B6v7*}7Ok2#?}D=$?VY%kA3>{PmQ3@y!BRLjTJ5pS*3f9vkg6>oIwu?p+V8o_s<1 z$FHYnAgJLmD8z|ox^wPY@8aYg9vfF4c!lh`h!-dDx$krSCOVM}EE)KU7DLNhR zg$qftH@irmEjckfG0wqLnx`PXjTFt(5(&#%qC)Km95zcDm(5IzS|T)4*}~|3uQ2xO zP4uKm{mT?2``z!wq>2Qs>g7K@R4m*<5z6mcbd#R>ab~>)357bs-&`^0UxGx6CZ>-& zIEU4bdCF(!J*uOp7l$oyh*Ur-4GWbo<{2E+ekFPzNqBYS(yhsKd1bT$27I}pGHe;_ zOIbAQc+)lhM2p_uv#@uUxoGl4=>#H{-|VjoN6sRk{@qJNI@?c!L&Q zF&Er;U%0t(Hn;|k_s%_DY`m2!H7qCAHzLbtd*ANwlph_Mxv+6mmTr6ooG&n~3(w4v zth2Rpj#l-S^=-UW_EpWk%WRU`A$@~b1+f95^Go?Yx@mmL=!Ve_tqVpM@aq!g64DK{ z9Y`0j+E=Zc>W@ocx86v!f@#s^Y}RR$WkIf;zRm(ra9%<$;m6QRge{^TvA~c|a0s}B z+`?|5P;fZTV|=tXcqLfquAf)^?7;_c{>a=Ns>ej%ovClwV7Lx2T|#pMPj)k161pL@ zf6@h^^GD;_Uu5X|Kz|ssb=L!w>qfc+;r{ESbcxIjD);@LPJh(?lgS^ah|PYH9H#6% zG$FcRUFZ&U4~AQV$A!zvEv??>U|X0C%uW_B%l{rB&r|3j_#9>ps~!D6J(hZ)p7eJ^ z;_yU$(Elm(+Qa1bn@WCCWPD`$%Uo0^MHMM^x+5MG9C?qLSB=}2{fpt%FnU;>tX|fS z%gLGDi@|?gUN&x7_Wm6~2F=?yVr_R)&qVsI2oRU!Uxrg;zV_*I#rpgCD80|1G)zJ|B29P z=wAh*1JR1;L~N60Y< z3Ji@R!x0!TMSIB60SokYBRml3mPP(gdruw?RsVfLB+){aY)Q$RG5eU2osu*mvPBwZ zFv2i1*0K~OOH#>RDWp^)BD=DdEo*iqDlKHs{<}l6e&6@^d%o{Kzvr2G9_G%u=bq2G z=bm%!=PaLlv-at0CB+ykWnLf?w58N{i(LsuDA%&mHp*T>To!(Mzkj=vtYUk4^OIfA z4T(IDcyOatU#X5VdAFsh)uhh61O2beB9r6X3s5^kr$$X;or)=OQrXyw}__MjqK?$VByq$6##_fHj4H=W| zm9Zn0wQ`wq_17DEE8VhXa@|MzMm#7KgDmNfGksT5Z?MetUzUi8~+fkV> z-(nIZf4|>NS|Kp|~ z&*Phn{LM8SI*&&i`45Q)Xp$PAma=pTm$-kK>AI?RaupsQ)2nXm|K|ES ze=Mrd;_QftoSJL8!daxkFZ(Hv3}H{V!PleYHlh1{AAj`R>R=kZJ3B<2;V-Oxm7E5V z1hH#u`m;G}=0KDXl8-g$7T1&S`WZX)%yiE)KXu~0hk-tLrDif^8 z$8JbGue^yhw%#7rQWTGJc(}Mp#2OoI4{O|!GXGr^k8}V)EeV-9L+#JOGkyLZ&A$3w z;(0kkv+W8)<&)*bEyry@#VPSGND{|D#hLLh(zrOWacSC3MRyU`_F*NDY`;=l6pPp@ zfjxR;`_0<9;cPu@x{gP^sNXB~+)u-HZc~#oUfO?E(tUITai(+Za|zYXkLW)OE?Bo| zr+fMu;W2z=)PR;oEKI|s(U>(dMXP6F;Dau}o89n0U_2KGEuEA_>sDHaC~Y}+lR@}& zLiQ&fWkor*ZS_$uTeju!uJ2On>`2su!!t=w5p!>m%&*X)+MUS9)X!G;@ zH*En!QW`EDDNf{|XG*st2v1)|v~f>G$Qmci?3y_2IN0CR9oelJY(ws@H7#NoACq`% zz4hI7@g2@l20Ut4MBrREqq6e54#K|Kk`2I80O|@+DnOAe2ukqcK?x*SR3H@Gm422BRENy~6?F;G{z$`f+ZP|^W&4t^blH7&Yp^}1y+hCG= z3a`T?L3OpT-2R%{!H25vf2|iV_4>HU{v1OPxL|-8owu%(2LMW%di88dKF1IWE*NAs z$Xi#=b9#Ik@Zyk_MtNG=(Ix*hjPDVWWG#zG!gl=}HqphG&SM!jF}AYXqd1ib)7m+h&0j>6dViXA3XEpp=GIiT%UOr6!sHaYyUp-J~X*gQr)6p!-Y)m z6O1ZQ<^4kZDImYUUJ7#JTQ?+b_0sm|B@@HMqzb6m@s>Xs+% z8VuLp;##r)eI#5ol^9XMlK5Kk=DW5+hPI=D%n!`&+`?&43+iAQZ}s;NU%(j)UG8~M z4--9b*lKSew-u}r>Mzg0QD?Beh*I4uOyKtOT&be{qi$evV z^?h4^vU(xa3brwvVY1nptX8mBvYU-b3Bn3(Kcw}A6HF7{J-V79 zJX+VET`5HBs20e1mo4qtmhF*|m(~76VR9xp*O)YxI&OV-yezBfsnb=b*^IW@nY!*; zo)aEHg(FI#`u!dGChfL;GY&s{c7N_bi;dOj^u+i|jkr+R1!XRBsJLU&Bz+ru-lhw* zgsGI0A9SzNTW_%WG^4+|BFt4U73^(Tcw>Ax+crYus%9!vQN33<{}vraGi$}8n=d~+ z&!hFt>;p3C-sp>R)@*@Un*-msDV+KdGK7ptX68!wdbI;>4ze#ZdLQz$-h5 zZZYknObx}z&AR^VA-&1xdV6eN)*Y?k%b#lmNcA5yFYfrI`^#tgq!+`wX57KzwYg#s~MH;nm>&E=|x9&9kR)3&CKgInrFTqhNONsTUvJfh)eb@G~ROyd=?5Vfkqm#!c z>$T0Y8RgQ&3@#HLA0_I37A1o|ep+y2E}r7NM*(~?1$$BFs1g>kH_Dj=11V|aU2M2p-8jZ6)gW1h za9+l9H^qW3GhmYszfS&H=5z3P(K>eZ*ViC6ae)k<_HY*!zE&UQeUF8Oc&}qW$ptI; zrOo994>2!R#6%psMD{=AOGZZDjgG}CWo|KGe#1N-tQ?e!3r3H=yk7)uGmqibJ!)Uk zd_UM=tEy43;f=8C*Q}Mw;!m%09qDjTMAoZd6i>;8#KJac1qJJK_V}duol9`a@6Ox(83nxo-+q{<$AD7(t#EBiM{eDXhU@{qUb$xZPlWTMeU1V8T^ z21UXdA^c+}^&-pXkq33v&fsG1+7t&gs)te^KNbM>q6mJ9ZEr$Z0|G#2%Ch|Tyn40^ zxh>hJau39eNx5IH&J+u zYE@|RG@i}4lhki=FxN#J6Fpu~gZbR>@y7%^%J@}PPLUIs{60>v%H~#EN#^*oiJZKw z)~C)@3PU#-l7vuWt-X~QPbVwe$9nsF+rLhJ%$Ob~W;B!1$NE7z&e>OIr{eOAJLUQs z)%xzVwvITNnwpYGmL%!PhCYbKc*HCLEjTri*`6=tJewp`VHM8oTy&fz6l|_}F(h85 z>aNqXDIeir4XY!pP4mv+VgRf=xlTRXk(kk|pP_NaZPj zmBXfmCl0$Pn#v46&(DZ=FrQU;_rN6Nb6*WLM@{pD%tj^1Vl7D1IYI27G1(-F~h4g;Vzqjfc`I4=)u)0ipM0 z>nvkt1U8^6eG7U$cM!)pUx;&5v~`B$o7QSzG1;u{ETJ;VZRc;68xXSs!ve(adTv+$ zUY#8m6i#7DkGvw!Tf%FeHDInNvw6{ufIXYy+5t1)MTY6k_MaWR90rKi7= z)!jp@ovf_J1X|^!rz3^~22}uOf_`vPe=TRSm=s@dCejPe1PVi}wI2Nc76=%W+X+Z- znc`lbDHhh=%OmWC6Ctk`vkztsC2u>Ym9y#OPdDjc?t+O)T?%^t>yjW}nWng~hGH}4 z0jORqgbB&<<$-$4`5J4HD^?(_fe*X}T()e{uoeN;sj+QhjKVcz1FS*cL0^~#v@a0e z$6k6+pt>oAwT1WkP$}1O2`ft3C)qtAFE8BR#Z__FFUD6fl2Von;9}cl?_K`8y z_~In)dFLbI6<@_%)J>c?{?d)9$W^hFn*fQ*GKQRFplqPj>+-BKgIGfJBls##SZ<(j zv#})}frkeqa1gt2>oj*!gCQV+@C_9gx#6x{_i=y8hrk#v_vF&H6oT-23SNb!Vrw(ps;kI{BV32d9-b;jEr`D1t&I$`M#OkC^B9}kI|WQf0h zIiA|R$Z3XK;T^No!>9Fo? zPPcbLapjli5HaPACs0bG8!sZ2Oq#i~l=y@mrEiIA3~6sXt=FV+ns10rVu$77(5&go z=?@3t89{YX?;75#=s2UE5%ivDekcwYsV-A~6?8V$LvV0HVAG@77Y29wlSrcqKkYN8 z$ru}Oy;d@Ufe=;d9F-}tEfol9VfWl>Q)l=wzI zzI2yx`n#y8>9b5V8L4GlgMp$ty{4Nvt1mxnxO5}?f_3wUiKG}K&zpHM)=b}DB*lDX ziU&5Ce^i`8G9J5{6l2X2jWAJa;Jlu7A&!52g0a4qqt7r#IdOMf_15EpyWE3*K)N&#VuFg5}l9T$BOS(%qtC(JnHlSa0l_k!|zH>Zm*l?bzt9 z_jZ8%CG|p3hL01-LUw0uZLuyVd!wV%nXd}{$g$3^MxmW~qwPEe-aBGFKqZ1xwReQ; zEUlgeO%-uW_wpGHj{Um2gSwoM;7(?MmY9?`aH8>ACy-%GI5nFWxwe_VVV- z9vtv4R$(P7S!e{(jZzWke~Q>(wKTc@pp?U=z}-_O2}DjPi7Ngkafh*yG>@dvn- zyMwd)*>@iM(`!eXn?ID_9Qzr1_htiF{iL6##}VU)HLd1VE!L%_O%J1q?&r=$t0G5Wk4{CpMVtU*b1M=*-#=y1K+&mA{hImkvmvl#e~37u zId)Rk&HqkcMnZBL`+YUu%9l2Lfmf4p9DB=87c#}dSYi(*Q`-VUKA$G=eK%k}LIKd6 z96_kbHj&A$^`Rv~Ge)~m&ER(7orw?5?eYon3PpOKebuEBl;aT_=JMNZ>u;s6Iw>l{RU>H;aw+quO6Z3~cF$+p`DVGcS%QrPVdsuEPZm14 z-K@%KlLRZYYeanXeWO#V0?s@tc49vN+FQo;Ow%fp9yOZF1txr(X?+`rR#&)BC0(klRx6brND}U<8ItqZp0(9-M@fIy z50CKMpR5uF2)%nApeyQjfHh{fpI&!tm$T|x8oF42KIUjkISJIu=gQ6|i)HdTzad;dRx0o1}RdBJ#nV%t0Ma&46L_0ar z{_K2F5h7krR3C|jVC_{1R>Z?@WP*;{FWRI0rU z80_rqEaeQBB9Se@Pz(kG2HrypgMk1H5XIGwigN+kQFhN0S)jAfkVGWeiO}fc%t($@ zIZ;vCKz}~-4B9Ul$c`d4$E=h&$rcRk07IqV;6Ids17!iAj24-McQhxE<(16IBr_aU zM3qRP5^Zb)w13Qm@`3kx(N zS-7eK&!CovK_EyF(C80?=|V6v5SR=U0fHc8Adqc*qNkpI(jArA2QxtKe5XfC#5fl+iM?6O~-Wz4$Gm7{K_8$y8di&b|M-iJnoE$3dz($qj*Ro)Sht_;*d8e;|}Sb)$3v@{4oz@b1mj5!1Z zN0`IV(l}|T1r#}FJq7CzO)$J%$oSivgfi8rAM@Yl)5Rf^700$vp(qmNn56oD?TrPBDvZMwMrQAA4-{!UzM zi$O8aOe81j41~OEWG;}4y%KYw3ox^%1s(eqCngXK1U47rh(jRa5@01qsuhX6Z_UXs zumER%CcSSV+*~tclK?M-rGN02ho!~~ajCI{1Q?hrt-;Y;yfn|z@9EfoVrlt|Ysrbt z&$uLhFG=`MfkyD}Fk{Km5EnARVlx}Cmrik4F z3=W8LB@6{e0htuqXAuvDM6bfbz)?U|X*nJSiCGDQ!BI#c9kmP(21iS;!b1ZS_?38Q zBrVOe>{vJi16|1<912AM*_!2e2q-OYv;qdFC4H8|q*0hvctCI5N<0Jqx<6R32Kro??hokxfbI|I{$N1@bbmni2Xue1U=8&70o@m+`2Xb(sAL=wShl^HO;#4HLv$n1y3c{92(SUmD#_IOj&vv#wV7?t Lo`af)HnaT?Fx!WV literal 0 HcmV?d00001 diff --git a/lib/doc/Float_ug.pdf b/lib/doc/Float_ug.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2274017b38f4c84cd9de33d25a4f874fa69ad3c6 GIT binary patch literal 86772 zcmce-1y~(Rvo4Hl@SwqhYw(4;ySvN6-Ccrf0t5oVgA+8kyAvFOYtSSR+yeY-k!0^| zIp;g)-uwKlXPBPqp6;Hix2mgaYABV&Bp6wqv7=CKY>rK#AaMZLNtsCi0#>v9Xq(I8T%A`ih$-&Of⋘uOUlK; zLdpi<)E5vy0ot2^Izl1+>mLe|r!&y}$4IQ4C`imd|5yN|4<%CjUo;kWX0CtG09>qp zr?E1#a{iOX!S)XtsNp|o01oEA)7V(KS^h!eU;{A*{P*Yl*Z?g5XvfaR@sGK%vvL1p zE*#ANLgV86#~1)s5I_GmE`Xi$AN_H%0RGXA6Tr>=_j@_H+5T}a7l7*@bLM6P{GC@U z%q%Q_Z^y#S$^3V@u`qLixb)XKv#_yq{+-6m!piaw`7(p?^T)le&c;@@KxY&r5ExZK zI3(rZW?@ot2D*a*$HvN}r2;fpb+rRwkcEp$#lgW9giQ_*epQ&H?aduX*+J6oMN2Ztm2%^T;g0JTx{Y1PGK=-fG{&aRD?@RfKN<97$i_pE^%fKHf{jB7#D{) zH;bq!fQ4I3OjJTbLI4bDBo|j>XV)J9W=27xq!d?_KtcK);2>aggPs(uLSPL7+FQ6< zlClCgnM6rhx!IT`tZZF@&P)=v#;!myps9lykV%@9jfE4WUaXv)Amw5OurR5TvT(5q z2)MX91C8xK`m$hRWMl+7)Xj~6Mr+<<9sPk2zKW%4phVtmq^Jhe)D(GUY%$1bPG(lz}IdH5Ious1d-rec6M(-r*?xrGxCF{1BYX8^}qtt48dY zwv!_{1QR_{gcFAGfK|Cbb~bcF2orfYiFHyq$2Ddx=qlE67Y0&zR_1}rpk8fp;p+A1?Cf1g*}yO}vodvca0a1EK;S3*0PIX^UXH*A;Qd8F zCMxD&2@&=N!?KMMp#)D{;`Qbpu@I2trmP%6q8mYM)FF!e+w33k`U5QT#?Cfi+&+4#Y`t(+9?gg63fBVDTTu`Pr=r z&=xchNZ(0S{#-6Vs|$$mgCnBO4vr!Yp1NR#0g7jCPN!Z@r!PNz%=|8j^BsrkH zD=9m8-BS5EwI4Jv*F+ucT|w0@x*TAeNvcB1!TDeyK<5WWfzDv~fau_L<>CCZ9oIvL zAo@dleUN!^1?enU5FlI_|6^7vKo=Wf9&dMj=ZTCuF`EkL}r7q)k? z`s4Z!q5LMl2T1<_)qj*9=YtV=uo^$)$Ho2c^5cBq&Myf*@CD?tf+Yy1fzM#BJH2KD@_`~y2bB>YQy4|o90`1dn-oL^7z$814uz-2Hme%1XtKX3*#pNFUV`Sjp1 zf7SnZy8k&!9{K~#0es(&d%->Zzx;7>fDFKYg~I{iFHX2-{EX>TDpw;R}OD>S(3LZeh*v`tc*Rc z8v#SUdnirKljbzVCrXZftt(4H+1Uu}YUm?^E2c~EpBYjtQlU`h1yX2>U+IX{1+(y& zGMe#Qinq5rCb=2KsKJSHh^yN4gL(-9BZ zU?ep#Bxuc=eO^+B5}oNaD`0y4i4MbCbp1Y$P(?;_9)=#)^!4C!YrIYOX{`Sr~+$;Yp0uqUJ*xFiJyvPvuBX!K4i!UcO{*n$i zcHdKS%PJN!P^mE_pYfMk1bc+)77gIj?(dh>E~Ok{qWp}2lotwbX_KCQBklhG6T634_?@xKGK8V_*ZRU`?r0@@7nN66{HP9k3iaR8J{-f zBpDb|vM-t_qgyMJ7$NWVK}?rf<4>_b7=gt zdI~aiWpjDX)}&kgVi~(O*=ILlVq7L)QKQUweI8;)nXjHM-M%-^F|emIV_c=&s-L=% zgj*3R(suDuAJQ;t%1y#D>5bIb8$6Sz_feqPv-ZkEP(`CKc#jLCqUbn&i&z?))Si_% znEmScMh|J`q-o52S9LdT2BCnxA3Gnn;N|O;b*ZpBW;fTZuoXQ8JC$ywDn%}0d064P zm!;Y`ms?)BEg$2l6D78b*Mj{hvgoI%GlyXh2Tjkts02D6lm5V)<6f~;(c-dH50~VO&LiB%pC{)d?B2|55k?CVGX&zU(d574`_C=a zPfO0p0$Pv$gC&<&TogiYz0n+*&^5Mbt%EK`hnJ!#652POK^9KJau}%Vi<_mQx;@KC zjm;=}3;)ebV0F}|`C1o!P)i2Z8^tV-dzY9(Ogh~Rf7k09p}Q`|R*n^ltu0W;vi<|F zS4qNMa7q}x0=hD0SJTrQ`H?Ond@W{kyHcBGywf>*&C-BG{T6RDN~cP6CT}6YlWdH1 zVl~XMS0W)zVwOG_@=lI8T|+5v{FPoz`jBJSohP-1=~r6qZmwkrltoOA2NDhYFHL>9 zG8H4Cq`W#ojynA`?@ZpWG&t|o52;|3Xa@1F00zMGHs5ZW*va7?lA~d&!+Y{~jzsex z%q?X*!+T92lk^+Ah)e=+3OIe@jN+ODpF6j9*J|j6eZY?yj#udAO>|1$=^nN25GK;F z?ayUazfUmMo#Qrl8Iv;+=RVeZt|{I*aMR~xhg>n5Jv{4A`-sYd*`J7bV4lZur^eX{ zTY{}-68Q^U>zW-k7hC+gPLU%rjr{gix=f^(bh5M{cFOWGiPvVyxkbV zWjcKDiFRqi9Qo?U{leOHsxBj$uW~Q0g8n?>5UMM*Mv(H1E6@QJI8Ji$kP@zvh@Du-*jpS@&g+kbv58|(rdFnm4^?g*dejN1hhBK1p3PpqMj0%F3la|2kRKZ( z)o23@bTTn6(SDUUTolr%|fx?m?kicD|Jav2)cw0B{A+jcZ?(UC{(sgz>=hn*{d=1qyUrhX zfW7&D-V3HY><54D34fJ;P(k~Jhr7VOJGjIJ-c^8G{ycu{o*rt!dkPTsp+Dx|J#%4a zD`VULJAWL^%pWVL>JNXM>%k{}@W=n?{(tI)v;OXd|8TB4kGMbNudwKaBai@68DcBmeTfIaoOUcdqxJ;fi10GN`xz-p0OqwF>r@`&UmimvX%V z7y1CkCD-Fr>TI=>#7c(A#biM>D>T9{>xKi`o5{_}#CRCvW4Kq*0t5vT{W3mDrk`!PCHs)wBR7mx1IwD0~ zi^Mx;&1K;Xry8JLEsr@YMo8wdk~i+c2rbx`OtevDO?5&!Bn9D%ExF8hG}FtE(;d(% z`kfg=-5Q>**PpSj5y1++cd|aBo}LzBbT2I8#;0}3)37Vnij(SzbJFeu;^XG9F5HR3 ze#BPs#1*k+CbON}{!GN)(y%QTGDt=hBdn4lyEJ0if`SDBtthbSFmHd5( zRAikf`>BNI2({;k72go?QTkicg7_)uj4zQgNksH>mnC1aO{dO7`$~2_x_AM%0PO@} zX_*A7V4k6sSS9=_WXw+Dm!eymb}I+Q8JfXUDxc?G1Fyzw7Q=3v{9$qBjKp1a>WO9; zwU1JCC=+RVNm95XUnRz|=f3%}W9fat(khTAne5D?#BUUv>$-ruktzb8tNw~v-AUi> zDBWfsfB*IMmX~_n^6SLV#QWLMEi;1o0E9PjJNyGi!q4z;&y_;CG9*OPS~Nq-mZFhf z;ZQufJlHI*cb$;+q<C*FAE7Ksd7dS00_wlgPXY=V;Icxg;79gu-x@`fNm-$?uW zba zgMf!{z>ohw%o4c#e|r3R=bxqD`vQ;f`}N<;KWcxq`m^mX%HP}ny8bcqAOFF$Kkxk2 z;@{5yb*uln=J$SnAN5!H$LPPVen0*I|(vedUbao+3yF1K9cq1|PFoC<<;M zn{iJ__f^>f4vKPle86gRZYft8e0;ypN%IT3TvkQWuoBdj9_PkK!wjJwN0Jw1247Lq zb+x0s=h|fPM_~sHXI_xTZD{2yl?CPL3A=?kCX0Cif|bPSPUe>;N_A7C!jfx=9VrJl zJ~kqlJzKlUe4JRk*b&d))srQSmlp+VTN|9jLKK>jUTl@6w>CE{H&^SV8X)bz$CRNO z5E*rB=H6J8=wj>xPjFElW+8V@$D(MeyuS{und@^56?=|T&CA^lo&JFs?KHFyb=f*t zq4i0T0I?kkirp)?cIfAY;k!t6&lixSW3c+{Y-1c{Raf{a-MwYGU#_cex4?G}wikxQ_nF-74!;VbHC2YL7N-Wdlh!)vjs1jiVrfD!R;Z~?G*5aA4(zW-|V!C~vaA|C7${kJ>8 zbTxTU6a&4L{7i7f=_BCtEz}p9q0UJ1T9rJRb)1r@xw-t>PS_<1&`xl^woKx=Xfq}= z?<0qmw$vc}59Bz=99CYGKT|26Bd`U#(-36|Rx|q#uuoW8R1<+Q!#!(XD=6p?Ya*VWOLi zjmEe*$@mGbIf3Eu3&i5Iwq$uR8>L%8?`TL8vP(I%w){K}qe$J>tRIB`BlO}EqAww? zJ$7QQwK#Og2?A9yv0h!-_N--_F^YlVEWQ)y@qD$Zo=% zvynL=GGFl9ig@_!YXv&(6_WbiCX$z}Gv)1;mOM=#$1|=R7U`*;&ArOiY;VCNa$Q~G zUNo*+Vl%uAOf2O{a3V|cBsiqggG3^{G>0N;BC>>h^4hlE<;82+?>MSLM<)?mC$@x3 zbO9B9!tEFfL{=Z2PfG`z2=0n|?(bDo*Trno5Nwi2zDnW+g-sx^hLLM%YQbegb$eZ$ zaXUoEK#S8nHTK2t+G~_}oZy$8or59mEeUgnzziYIAkp-%5Cy+~`71=Z{u4xf)fVju zSkV1;=(i^d=6lZ#iYNI#sT3!Xof)snJZ3aP!Va2w7UAo^6XT&v5L(&Ab{;cENMa~w z8}p$^=Oss#li4Nm$~39jAf%Y+=lsX@x9eDt?1f~{G5jI>f`n!`>ud++t|KF z!g0W(N{`+MwZn$?#}a&B>2a+;hdPR{^B=!F;;Y~$)WWFjmJxcXY~Y$>{dHPMLQ*_i z@pt2H@De_c*`sGI)!i~ zsIV4F;Cwb5Zc6hnYvc){`} zOKxM(V3Sm{;Mh(&K52Uy=X^H!HovMyVMGgx4Y;f((Jc*>RM8KL9Sx)Pqm#3RBD<9Z zSRp22Lm7?Bd195iM!!Yx7*DfG<*dZSlF5S_?VnFquI)BD$b$-vykbs=b;mvDU^(2k zdUmk;Eql(HV24Vo=-F2dlU2$7nV~RQb3q2xS5@-*IPN7nH?y07nbvuCpT=9 zo$~2ax;D6R)$aHH6iL9rm(zh({*UGTeQA~`0JS*C2yD!yIw9ZS`hc_wgm`i+;mnE$ z>RJHiUAdVi6~)T&#{J!|IdJ+#+{Ll(CD@D65*7Ov&SCE4YgK#3;-2yXn80F`k~bXB zEy?Y(bJh+YZzOHj#ONH&-}1VRCeFO)-P0bLzd{+#K+6gJmcn6kS%wk1Cvp6qYC=cF zpXGWU;&o30mU(*Zy=L~eRYw-JJ<$f~Jo#rkaaGAq?OhQ(rv>t(p-S}L@vmC)NW&7x zdZ%08hdlL`=19@G?8*0yT(1yy_VYm;yyQ*Kh;?9U*AMb=^!IlX?~8sJBl=B9R7Z?# zHxwaJs4Gsbd1gG>N_`%Qd053^8Kz72E&7-9r{SAuyWcix&;kaaFFY@o;f}g|#rk;3 zHdBXNuaOoW50T2^MY=LbDswJTx%RFcsa2I7W9ODs9vib180UB<0|!ZPC)8x)rc&c5 z;)`g%syt)9b2v}If2`EEscJeLS2vtVI48CsX+K&3q-0c~wusNl3_S^WJ*7#qU6nXJ z1=pv&#BsP3xqi~=J=)~XKV6ny>Lp)acm^>MApX&=ELIh|bRqbw0iVZNrF9k_eynft zykOt+)NF*h)SQE~dwWRm#%|0V`utzP^k=YFT}7J4($&?Ghl$C1t<73(D*Ob@JOw!H3r(e}O71D5d6K zunI~IWn&TsXS>;hQdB^}8h0yGpo*l(@9#&_lfBebJ#hL190oIACRKKuqUZ)z!oB3M zHI65OQAUtPfW#D$nu8SR|qMAIbP}4+TO9p9`MmRjqS6uTyym z=dRp2e!5qF5>=Qo*5@M_r#kj3>&(_2-)-)N9;8@}plVu+43S*sBdc`HkN8PkYqomXcC~7eSQK3G2lAGt9On1yX*jo9995fp zRjdHuoFcp6$A$*e3do8%_{wL;5Xbe%5L=TFDm5spK`W<>NeS?*-#Av+SH3TeAzojo zt_w`%YLvZ+PBhyxa?WkD_a8gehJwn5qFRHbH$qDf;zfrFK!@rQW{-d$BqjP32vzxb zK$v?Rg1-o!F`LLWh`5s27OLBb7Z19*)87$2Ciq1s;x|c0Vqe7aAYCI&x!`akI6l}4 zQUo&LM-j-{!l*ClKfzv!n$TcIg{$N+6hY7hslCKu6=57lDuUk+56dAMx8J=OSKftj zMQwudgOwLX%RbD0%?veVOl%9^+}T!%7Z;?uM(BxH`rKxXssYOY9<4L?o4_TrFO&e9 zVKDW2_%{Y9bb>BPLX4+m5)@KADiN=qdgo#9Nx;P`n+ZBU;*Qo6rizywKzd$chl&BTw%#9vNIvnB*hi!X>Q zNM6Udrn1X>D-^^N4cvW#aek^Tdq9eoaPd-*(vWJEy!~w@P5CQk86I(AtGrX?KAL_S zT-vEunrZ-bq1fzgCHkVT(@*#PL6I)IeJq05Z87A0;N*18R?X9eL(8nG0!yY{!X|2c z5vI3K_CD{DOum?Ee=BIrjAtKXDe<(sL#u!816S|mo1>)|n{87n4%L*})YudvK(p<6 zinMVPt7(dCs{DxX_S0?gZE~E@t-gdxvr>&&gwHge;cSvW0Hf#jY*CtDw}$)0`DKZ2 zG&pT=BPmetK#$Un>Obpp+m>l?K0rFayLjaBM)DJ)r-}h=Mfip83XDTvx+$?`rp1bp zfXQ9t6$Qz9^HKhHI)9RT(tDo!{Ll>Xn9xa+*k1qWVVp4rJBD1wq~zsfc!mn?wwkWe zjWW72fL5&Ta+O3Ge;HfZ=dyb3tSW!A?rOyP_(j)6!kR`aofw}H2X=V*itsPU-Q;gI2Dgm+P?rYu_6fRKznb3!|!M8eoO zUP5X@LvF-$=M0{7RIX*G0-orM;dJK?3TW^b*PYHvm>4(**CK-KaeO;42*RNDwBS!gHM+&b=-f2j@@_ohhGdIj%De6YPOtz zdjdNPyZ@X#G_R|rDU!;+AcY=#-*=r5P+q@KQ26_QC5t>1! zdDY`!27Lfs8VG`InmpvM2RMgG=-y&ON5Kyv0NalZw8gXo=Ka(|taJB;z0|IZuE=Y} z_)G8V$cjyTdaH*{htTK)N{1?VvY*<>uuIkw+U1|S*7~`Lo>6AJE|=xh#?q)RHkZhH zyQ+;m^Q@TPWNlqg6*uOfFR8D%X`m^-Y3I!AESz8tWg!eXHZ#_S;E;oo{k8z#E}1jS z*2&h&Ayo&b+E$W&T4%xg{fEY~YCCVQjbr_<)8|9yf^L^?ryjoTWC6WZ3eBTi86KKc zUw##CM zj;nQNJ!cDNA34SB=4QqY9QNCrS?o5~A#JmL)^6l`(?(I?Q0-UcmTi~#xL;i>LgYc} z-la68Ql!32{r<-C%}km|T17fxdSv=VhFQjBrch>i7ExAo)^)a3_FRr+PTgCox5>G1 zx$e2!c^Y~B`CR$M1q21r1-FIvg=olFSE^S!UM5!7P|jGM zQ-M$;~Z-k=N@mG;G1Zh6rAjw5}WFq zmYyD-QJ9&SRiB;vsP}Pg&TMXX-gf?I!F}OoF>ncXDQX#gIeCR}%|Xqf z(Ba58t#4aL&PVshF(>#Zg{SPNU1v&XE9Z9SHy2Tt_?JajTvz?qn%6rw9^c`=r`*!s zHr>hIE#2GQ-$OluxClA9LHbu;_V2F@S=fFg-2Gb)-ybQf|7}c~^M8`a$MHuZALz3m zP*nQQSBU@rB=Y^4x%jUs@c&)TJL?}g@1zgu;QyP%b#S=-S9bc3%=3R_r-R^Q_um7Z{LZZ1&ujt6A&;xKX4t<43t6+IZAQ;S-$iIMnhD*v zPpO5%3o7BkeU*ZXC+R2aN<{4aGMp6d@l{cf>pMo`{Qa)hUfh=ImC_?9S!(({-6s?A z(e#HN>ur~&?q~hHfu42nRJ=yHT%&kIR8?q>Z$2ao+5xgKLo(K7hzag6k`5j~jNE}xvtv_2g4K=0t#vjrNy}9 z;a8O}R8{>K?b!4?NyVoG@lhr>Kr-k$q~#=v1{57OIM#74A`7QudN)8X;8(v|faBtUKeU-Nzaq}M zr*AeVK2#_&dmUkltCa@tY)AWMnVX(p=}?eXL3Ut{}_hgW)uJ<@wz ze`?Xz*FXB<>oPWb0qJAfe%*kelJ?H>4tyJ*!34{tCA(7Wx zgP)YU$dyL91_!V+?8YBH(mYQ%&w&(AJHn}?FW^&JL48rP+;ksi4*OM>cLrKfW=fYS zgF55tleFmqgVC^Mc#u_qoz+Rq3K9ON=3B+b@!!l?P)F-l+C*Uc(2`;#=+#`?M2OCp zU3TWgCb+BKDOI20Je`0zSxB;q3UjWeB~gOx@lBjXU{)gxv0ToRmk5QEEh$~GfAd)w z>P)&^M1Wr;cAgr&cZMeyjT`Ai#B9%(F*ywr<*kkw6WFY-$L5jQLFAX&Z^lqeor|93EKmse9Ha zXb=&@hidaeKKD7|8&s{_(PD6lAtq&6A;MhGfl8kXgSGrzW&MDL%Z(BZk5MCoMLk7= zWd|FC3zkMBHyzLVFn!lbc+b9=dk~lVlIi988BM=lD-ocI1mi<(ksHKwQ@fv@ozo>O)rkSFRP!`$U0V& zAa{PV!nHI}ilzYI(mSqhDDrf2b*gpW@#3(-kW8~KBTOvsni0@;cgVxH0GVLNKwE*= zI!k@n6q~No9;IUX8++9U5t+Mj2zi|nxHeN59t215HXQ~yO@QVXCv|-Ixi9qD&=VD; z$><11zEWBDz#d6=d1Zb$=v>4L){2|dPL26CKTD5}Vf~!~>x#;m8YAa}bsV&$rnt`0 zRNbhQ0n((zDpik4LtC)uwz!11{0P1G>jcg54;@TCx9A>W0}8hT1Fjb*wC}7@d6yKD z8PTnzDk-UChGwJe%^GvG7*z8dr-})cR?t0cmRYGyBBX0{a$CkKn`D~LfXcZw+>Knp z+nxUGEa=?&uU{)q4)#(Il=O<%eL6(q3QfYw=r;+^bY~778KfbQYViAtjsLVsck_JzIinrR8=F^f{)>BjaLS*c^#qo$Pxog_ZR;-<7$rEi&ZtR4aN7%eAB{)IBFR z&)AK67n-AtR=@g%$uIT!!oyhfG9{-oyohsj(8rW^u*CL@=Gr3~I>KeuMe{csM_Q#;tCpc2^ zq2FLE&83MP3nR5QP7&gkNbQQk_pN9mSiS9XM^O}z z?;_|&mB&cjLSb(c)`6HqLj<{uqK}l;XS2r6a){kgPP66iHV!Xhl}a10 z@1L}j6jinpIL2G9`oAJ4uOjJRe;MnzN%ZYyoQU0Cq)!iZW(5pOVgjQsa7ni4>5Q0a z1fA=bE{g-+HL{whi^jrClq~Ua716s5%b58G4R@NQ*~Vn@zUmsk8tj8 z*}=;C_{AY`%DV(w5DG}-*&3TeBvR!#NlhVGZ$35E!jL}Ou~JIfp|9=enEf>CO3;$T zxg(Nx%b*eYQyD{&=;o(=+N+7!A{-6)#c4)J1Frep7I*`1`NyrieP=X1Z4D$C+})~^ zA4HqpDG~zIB?+5wNzhErIrmq3h!L3+J&}|PBoO#ubY~_egNr^5YL;tUr=%4wnAlBi@17O-~0fX~TsV`)G+m=Q#Y<%f~{`!f|Z#o2qlvN< z(gp2_zM54`nk8SgY&@yht)s9JY<5iS=&?PGKYqU7?XB$I7eTE4dGcE&+}BtSvpP}_ zM4kvdhos|P%nBf)nCcnA{R<|J`npvm-ROx@QdW7=eqNnpPsQ3D1mPuhTn{#yW9cub zYs#2`CU~nb_tdRA?n{8@YZW8P@S^D9)58c*J%a?_W{w!)gXm)$Ld-zAhJE#UN}ZoA zuQVJD5{KTJJ^f&>{GjBVN`S=1ii$NVbN~JR2<nn@nP|8Y4=g(RMJPkcpPUX?1#ZM0>Ogh4&ZOntf#1_i5lYU^ zn)S+=O5vs^X$^^Ik<&uS0XS=3=C=$H9ywuR)xuIrErF_753Q; zYs|s98aL_fwBCi>H_{SBq-G?N_O76p<=2>(X(69dsngiu&zvT6^61HUSgd6%EvVLG zcezrnY?~P5TeVryRZCCE#9$0QVlhwade41b({d6xaRyyjD9a?ai&4(BA8wy9d{B14 zd$i`VER{K{ygqPC<5yygt%Pwr78?lqXdX8RC!wg8yc@FZEhRf98-~zROchJ#d1xnc zv@Zr^SoV*RdE_Z$Y(_6>O+I7~4*7(H6Ze{?(?T>1am=;Z&6`6`@rXEvsJp2Li|k0G zd`qy2Hl=@|b;z)2iJ`U8tb3h%F}ScZq}tl2 z0N&kGeu5>5w<1>0Pm^@LR?<;ngP~8CgebKO={{&wr?5n&H9_ME)2fLU@4r%sf{D7B zu{&vVgTxSf6b2!DncbCWX}X?&*Hxe#nhQNV55G|nh(Blb0=5GujtVjwpE>uJUetom41yy zS43Jvt^)U)iL?cjTc~8o+W03DMG=orh__LSLW%ruE)e^s!ea{8 zNEP1qLdSITCYlZJy}^b|mxVZ3gA0OnM<8q@W%|yBKBKX1SB8Ue5V86M%7faPOS>T9 z#fyrR*ow=-NX9ChbB-0P1u8IpS;UZKw9wJZx0)pC! zVHUhSFOT3Ru?u!(i5?-v>nHYyL+^WbiJDZ#Mc08cr_KS}Uy-Ep-+{5>Oy z$lh^bSz!2^azL5=YO+!iE-iw8lBi^#IG>A;>>^P>7k9;k3d!r>KEzPnvDIX z+`2%PwB2`xp(39!>HKL@0688!v?7DpjuV5=06NH}c~RI5*L8F)BUil&-X>&QPe^Dk zzQIfiNG(olvc7D5%nf|%;~h=%)_PdtZR}kYW(&w+2okWaMowSLPU(nX=o46iXo6B$ zcWuzuBq?uJdw*)IU7Co8BW)cjWUVr6T|p%MQDos3)t{@NNUiSG^On(Us)%C1+k3~^ zaskcjZ0%ENol&fcPbyEu%fhF9S?69PM+L$yynFeoTFU%NJEw zzTXFb%m47@*pF}de@0RMUx!Qnks`y!$^4%Z2GTVbofo+<{Vp`u;+I&g zpw>7N<<;%kl8WC7QqfO%Np_8=)J}D`?f0j*J53~!=k!fI zs0rSbYi!V$wGOZgbt#9(Cz$qnTon%nS9dH zV~X2MnqmAtY}TBzaufd0{-S2&oi0Ni7wkaS6M4U9muhR2S9K=s7rs&P)tmDufbXQD zPGO8BCPDB%nv<&Tm4vfe@~u5fQuD^4dQ6uUk#S~c+wuTAN5KecZJ4oc^m5)Sp4I6# zM_OS4rcr@=d2TPK0afl#dwM#=vh7@mx9o!nxU9?w@(HwxGMbZ8K$_EdgB!md z?KSP|v^X(i%lEpETViw*51C87Jta#x9Gq!~dq2W$wow$aWXr9V_GIFEyd86hMR0j) z5`OVA<~iq5HLHJz%aK;yhsGqeH{o{OB{rHowxe(s?c0)-TWck)>Otm;xc8*1F*E$b zZ7yuoJ1t8Lw8O1)#pijccgF?EwMnHSkIqX6x|1AU5lYLPsi-(7lYEfNxN>?GO3gaO z#o>u%L;&x`+_Ujouzhpkn|n$LCY4LgLKQ&{lCyB3f)$uPca2t|N@rTwZ^Yv07jmemWD zJpjThjj+h8_oc$O>%h)gC=Sg)%x^pgjqokF{0f)mFa?TRNZ(rD*}`Jcw=73dB42fG z<>Zp65{U6m2j%GD@e>Jma7IZ<7mlfvH+DT1MCMdSRX0{?YLF91hG^5X^j18Ivw0?H zdyqp+BVib4n9lz${2kKvMDf~&WZk7*8p@DLta@^zE8r{2G1NHDp&4PHQ5{|LMR4`#|_^I;unZ zmCT!OJT7zSg4hfJR8^*a)IQsBP81@lwAPDCFQRaWlZ~ z;6-88a6`;+DP{J|Un9+ThLCg;d)4;&4c=0B<6Ks>uBm=S&vyp zTEjwt5fi~JI-&iFVUD7O7_&2(L90)aG7EFjt)4fEbg`Pjf&>PVpQzH0_=KjlI?<$YG=(84mh>(gyT8}Cs~R0 zR-j$T0>#K;oUe;sp|c`~X?v|7#JuE)2~P8t)7lAY205CW`}IpT5hWY6Jv2Qi9`*9K zI$qN%h~sxmS%LvLh#bZ#uB5Nw$x=}#geIDBS0e?Y?QEV<5HhVY=;6?*y9pjDcz0!p z@;@?+XpHeAQdo`@-BchX_9(P;|2Q+oU#N_|a4fcbFz2e^o5mwi`~8)}e2arj+#X?; zJ0rp^yE^11V-53KZ|%O= zDu{kU8dk)-8W*vXhf6!nIJ|qlDdZFbJK9*m_Vu%;<2`a>8DY&k=zP|0Ya@e;k-f)h z2${2AU|g(3hda*eR)@nX- zS@htu>nU;sc3`LAB_rxZWI9R&3hq*x=h}=!HsTmVbTUJ739s6_Pw`w-fRYwC%^N_s7HMQ$cE*H&jco9a?7lVc*0+|XsUDSp0HGX&ah^YLf%FO&n-vL7pN za1yP;-e?4w#wrK-Hqb6QXJ*h}A)l#B(n9EGl~%}P6je+hNU@!2ha(DUkkHY;eU2LY zE}wre3L*iApc)+#&}Zo#A!^#yU+5=A%u_7SIfz)D!|p-(iNf$GO}#hZpqcXo-ZMQ& zp6mP3GYdXhq8sHRxpz}v%LfN0I|Q($-#e4W?g>2)YLm%Y>)hv}^?8~{cdVYRSWj;q z7SlPCBk_6HGE!Koc!ZWp4PnnmnDz~~O&@_->7YFegnDO0ZU(%8adti+e1)d3?jo>e zuHl1ja_G_Hb%+u>1*T{4@@ks(T9){7PEH!~`f~F3 zv3c#fr;5$H>JVu0xWCYua<1dqQPJdvcK2#}H=xDyEZq(0-4Saw11(o8o%0Tre3`5F zc^Jw+7d~MM+Qek8tlAxGMie&LNpD;ehS0t0sECEqLJXwxd4JYuQyLv2LbR7KslCa^ zkLVMXL$y4WXRg6xnGUJ4vkb8*k{r#c3dllVgWP7Gqv4 zZDR)GH)!_=)!&iqs8^-~9*G5rOQt~f!37WIyk7CKE`04?u!%@D!Cu9N1Cvm3*jBGI zj~XP3CLc<1Xsy|-c*sG8`YDth^1ZmrF6yB0^#4cOJ4K1oX6u@1J9DLN+r~=Uwr$(C zz0$UA+qN@T+CHnQ_Njk&ca5`0bywd;+{8shjQP%Q&gVf*YO@D02qSy!mgb|vYk{!% zo%JE+UH4mfT_KY}6UDWSrNAAwdJv#BUjAZCa;jnN?YfN1ohOyaUhVws1pnfAi;59S z#IcX?_385>3OU(=TpJ|k;?2)7mSc%K$8~mcMnVgoH;D3hPY&Z*07%To>p-j%F?0Ww zR5hbLeUjoc$)EfabaF`8z!ck-VK>N6`l?$m21_-K{yhOp41>f~yXrhxvfA|`kf{!T ztaaK*HTQn%HzjDI!9+`u91>0Q1!z~h{A?SE_bbJv_y;B3N@P8GvmtMVYs`afQlkoZ zjmHRyd3^({sbqD4gXk1-Y~P>n`rvqX-H^DWsu)AJ9V)kM?~2B~3T~tt32KW}an3=a zwf@3FszMddtSOyqd}%)J?b2j-&g6_K+OZ5OTw{1Xza8XtqRe5Cnb?%XXZz*BkQ3xc zU#_G>40_IDHjXf+7e9vFhQ!hcJR3EGQp3xB-$@!Sj_y!)I5s+@y=Xd~pjQVtLM_xU z^{Wt5sv`BRq7RVst$_Ld`cdX(8FTYGv@#GCX8`7TzF}Gb&$o9J5$)mBgY*@&fJ~Q) zl0W1aou(c_G`OP%N#coqAc%x$`N?utZ=VD`Phi3%pB$6Bf^izO=b~!N)@H4N6&(FC zGh6=}BM?I@j0u4W4Kf#xUJmrx0-w)?=yw_Ndf_NeWBz6Q0=>FEkq25VY1ln+%a5)n zb@NP2)%j4aQ;^=@hMazz)xB~zT1PnC%JU?b_-PT*y^CN9+|i2-rPSLz?Qh&}_RM{6 z5OV-EP3_+k-)YGn$8V~&%fFp$E#%#v3f*TF8$X90o19WD%34c{run$bcU*G2y=yvH zalO3!#Q-vCz)%D6(9jmL_Ai;LiYP|o&j6b2evCwZ_uhJSsM##HEM1(3c+gPGs{3FK zH$?Zga=x*=mVNS&h|yu3QI*6<-1)BT<}o?%aDif1`3Q2c`3tTo61nxP z5QSc!vfEsSrv|{iBc+>=hMKIbSwKkT=VF=V5?OpnmZ8<8qnV0lIuA!`kQOt$=!m%w z;v}qzqmZulMOf8oz?6sk8p1aSI)E40R^q?N?0-$X|J#|J`LE3Ww^3(>|3qg0M^68b zj57Q+e*M2k88}$}r)-||w`?wgsP>DJz5?fo~;sD-EYNCcgN4yt&-<{WZRvuyRYolyTRje zwBXkEuNUz3sU^CKii@RjrrNTh?|5&>J8RBP@%OWOD_HfcwyBmQSys)bcrdQx znTTludMtTv#R3c2h8<55W=F z;h8{*lxbN+km$@b7OB@!EyW&lPb@9nF$tc&p{w}dsg%eMu4jeEvxjf-d+-WF!nMEM zXGytJF0e613xPWArzW6Tnd%POABHesV9$TkY;T4!PYhNmMr5|^Zz!3);TESp!A@U! z+Bc9peHzv6PHk6|FUOjTn+)N)Yp_~SnlR}Js}eLi24$ublwaNI^tIXQ-*aD%KNT-! zw`Xh3Q-1JP37$<0(dkufTQ9xs$(U-4XG>bNSqtTcuuSQo!OXU?-=!C|RdwtkDDF%>8Pv=nz))xNwdCFER; z3={CVluchX04&22lL*JAUt4I`6i`3f_ znP;*Of=@IaWFiC_|7zLw{RO9f)l7_{kskv_8m1&Q(Ng&?y4prv}N zhP(jKT@2xIgCl9r@?`EK0H&vx=iHxxL)Suu7g4el-j=}lz^RG*6}p0RRA^o0i?o5c z7X1F8gaQV1=DGtTNG>lI$)@13nVWi^?i1nZlPc_qP}!;Ag_?|EW#}qash=QuMp@G& zV3B=^p%h7dd+-Clpp@GfbX#+q`4b=Li`HfG}QWZcO<_Q{W1r6w3rsicHa9TT)J zgLE!qLLd6FHX9V2*gzFumcCmX$sDEc&h~q20WOzmN=Ixb`Xutph~9A~>~y`h-JG*n z#)1(14mexGUiTia!^8($K84Dk&}nh)#ydI$i%>k49wI)!K)P_}kq(D^BvhNYPUI&Sg?t-``ncVy({x$LWRm7E^m>kteRCZoY;dw8Y?9~qZC(%g+%u&CvL49X7 zzJjXUnhu7!REx{b4WMHCmXuQnvZN{gG|G8NpNLK)Q!nt7gqNZtjA}$JiA#Bgv-IN} z1x#Q`jZN`QPmZT#=mc;%__=?J<2P6|#$}ITPxjaW!jvIOevb6e^jpH)Lg#pb`|+u$ z=@BrFb`tf7I-!X~+nc|XO1y~Gv$u7Zza^mjf-_S*_7d&GJI1H4UW4web=C`zzm^tZ zoTa_LFzFRgB~=0>N$Kel@u}xYQS7bxRZn{~-a^voVV^4t@IuU39Zen5NWg6OGCaSt z+kqh)SMOaX3{oYSI~HNenCo`rlsJtifhHIP3Q zL5#_aJcM!l1`tGGvzJAZ_(q=L{G=0OW^UDzfq6nMj22x|$?jl&1dDGe?ztor6vTpL zR6|VzKX>R|*`GtDx(t*6(?MFRo1y~Q6 zm5;__I4f*I`ESt@tXE!!#a_(5w(l6&(Rit3y^N=Ouc*Dzgaw7ej5bkX5|V1)8}+gU zwr;&$TGHCoC10}4L5}0ZJ|7;;qmgsF8-e0NX^Vq@t!g!E;s(Fc>WAOsMC;HSi+cYWuf{?t9B*v(!fK=FnmC~ z@+Cr?-K7f?X~eP7fq3e zuMq9cFiiF7m*NB(4KAdHAXgX8rETXZ(n0qc%SyR2BeubwW=ScsVva^e&nd#A2zNwM z@Fu};+*wi5wbRpm6Q8{wT+%b?IVL>kw?yyixJ$t-XxASERW884qXAUATTU zeNkQUgN=ad!*aSTj*8$)J8n=to<#YQS@0M~_4xodM zxVk&`XmAiUnMaOZ-9o}R~19!01*heTs zM}=<_&)|mw!k=B`Y()eiB-14%Z(by18O>e&NuF;Kl{*w~8J4nPVBMa>u6u#%KY&Ah z9h4Eb*?E}LXk6!YY=|oDAqbzkc}a4g59XW2Te(q zCsAL*28P)BjB!=85!}QU3V&z536-5qY%(NtLbX-UE`37;Seheq$~ed>rkyE`t~ak} z>=+O1#_xDG@7M_IUTC?7(b&eW6hZK*As8zN_{YTHr+@UPd7IYsvHZ({@#jFp+l&W1 zD>%EXXb3Q|qhuy5SBdAw9P|;%ruRU4=%lwLtv4myPe?K$HVbx}@9K3K#fii6Z+ji* zu4p3Bo0=PW9kl>q`6Opsj^EmLy?q=;-hE*7db3C*h!t^A;%j$3vdWK>ad#4%#PA6r zi(U^-s;a7@WQj!RXkdAMg_)|5K)y69ppSvmMoa%#hkqfEG5Wh)06hy(S z-<^b3i|2NVAWh~WL9G;>2OSt}Qx!{XS5O7Ka` z6LTaPFVFmIF>Xhu@?w$B*wT&grh3cac8C8=6f$vgmh457_pn5z-GyWQ#cWxYNX?<$ z8;uc#e!`kuRu1Q z0`d0dRlxF7DB-fOdk>?@jCcKKXD@)sRgK}Xf^^&ODfK89@*EBznx8O-KCl`v4x-#Q z#7N>cAL^T&IU6fEiHuV{Be%G!0~#{XaG0#Znw^4h%laZR zu2vl5QXxHuVs23Bu5b>%_t z$2dof#)pA5yj&K(+k6F+E%_Q7O5-As+84s|a*i&pM$Yc2ig;j(&_^$n76E<+uB^L# zZf$yFnH~LblBbcC=4rBHqM>`w%EIxkI*O@$6%)ai(F`)b%avhdm)#{HusLQp7*ddL z=P7(TJo+oZLv658D=I4#(mIFqq%7fv1?-Sfgp4a$ zAn^#4@J+W)JJZc$xjvUcx=bxwkum!St|0m{(;ix1UPYs^4(SaZ!5G!TIYK& zp^)DM#!WTnL|}QxvYrc%>Rn5!Ht!FZOhbSFn~|8B%%s59j8~iO4sbP2_azFR&5>xI zY0eba$?2RyIz}ISNa>8xs+{x6EaFl7x$hcn5JJKJs)(?rw|&~-m!c$Z@>grgoaA1V z&C5sz9R;D7TzQ3}Vm)_YbJbQDpo8c*_C%p#x5|s&Ovrmq9^mp595YI!Le{*tS2 z?w)#CI>k~HG|uczjaBT;MToTtZK#CL%MsJ=MI#>9%r>I^iUCEyty6*@bavRJ9uqA+ zuM%jA3mIp2H!ebfSh+eTYx&wk5+G2Rue?ng4YbpS&?0rMi`RM7;9;b=nBSo4=tH&qedL)!PE(VSBp*1^te0zjAy$f zHKiq9`O7Ko_e0!#?I#WTClW^%3m%6dvhy)k1-^BP`XdLIhJ|`qUG>0FbA{>Gie-wj zm-%LWQhS@cPHggzu}36E>a_h1j*C%;)|knfiwI(TC$%VIR%SU%Q#lJ9)Eq4P%{TR-j`avtm6;kVu@}JrDkAJDN?-`1}^H>%zE%lD71xvT%p7$97dW-N$41fotF+w*4JJ$6ENZ zMJg039`zc(%)({!MK)4}rNWz=^$bW!O{#2thsOGd_j4+gT?;4cN8}dI1$xz`D9q|b zTocIW+hI2$N^9g-&JK>%`0LPGQ{aB@&9gd!K`Q0(&vn(+D<}2KLjdxjsZ(|)J;=)$ zR}lEMrK?rH+R(l`)*7}oC@u-&9@P=ffbq~c+GY|dLM+~W%aQ_*5<6QmFO# z*g}^D_wJMGoF}K$Q=%9|pf$KSkvHGdX>$j@@N1I+r@B^Ju9Cd4nSK54v?BcCwZ+>Z z+TLztD^h0hO2K)=xqd#~)6-8;0?N&g!j#_UmFaPww>=@x4<^({9m1jg3i%+DQ4|&xJujowV7eOLy zJ@IU{i*e197J1>3UD4Q2qN@SKWi-;nqkgi1g;I^CwXd^dR*$+zDbo$0_E}1clCCRBrkAV0i1jwht$?@TYfiLj@* zZbrt4({suQlTzExe;ODNid|^V2gq}a&n#JIuAbR;&JRvLR8kSD)i%sKcAM%-mj$qd z(3F5%WD}aS2wO@IVZs)=z4SbY%p_Euy$&O=C|{a4y*n8_gv`|7u^^C^`~HF}uXKft z7K)2F0jf0|{>6IW$@z4PtTl$vREZ|eZ*M?eoDirqXj?Tns!?}{v-44S&BfLnI@?}n z>o@vy0f}aq&P%(LKJd`z^WZE*UncpMeXq-Q2mC7RV9WqD%`-V!J~eZ*-w{xP9V26T zLe6*_x9HE0&pH~Jzq?!GhqWV?Gl`oO9I^X`PXblz#bGBP^PKHi947PBATIN_%7i4} znnZ8s7`#LROp%LU<@L8}uxkrIJZ-^Hf|s{{?KcyEKamCdzvw>xg#i7xyN@h?bszr$ z2mLq1Apd>8>c3A6{d3pqpZ1UcNGI~I<+=arME;Qr{ZC6(S*q5ye>#z0How00`4ZS8 z_Z(h}nIYqtg=>U0P|&pPL)#I^9Y}7a5;+s!h2gmP(ms3e~OS?V6>uKLpW zU^I+lwOHKvE~cxw#>@ z6S*jFMP!O6f0d4l^XTse@owtV{dAyF*>4(^oNHXGFJ*Oa?_4q0T$(K{94!}GQ|a%j z>&czR(<!8sa-W8T02f;+G9e!qMhn0R=HsXW+L$JefA}6{hKT2Ymx}>o+v}tZ3ya8ietaT~5`tSa zI7fUjd3#r@1Vne3-=FTb+-Sz{=5b1MPGw@7&W@0DFQR3NZNrk`VmsoTztGRj>+1oW zH4Q*JQfS-8wi~&^Lf2%$)CofxbbB-0YiTcf`Y1iV!txf-BzmpE_Re8ISKlc+Df5gP z-L(FUIQEyhv#twAXejMq3K?!ooy?j0_d#Y1x7Z!Xq)ZQ|545Z~qjm zihziAMBAM@mDI)@3d?PF@91-wBIIBJa1d?gLp_;R&2t#HgNA;BZ0B3!%As?hmD?^k z?;}Ez>m72g;_UV)XRlxbv{2IPIQ2_Z_5r-)q#WSPL&TWwoJBVboL8M7saTI-(Up1_ zed^PjvUuvDS7&XtNekKBF*e=T4!xlFKX+q75bR-U8#?!ua=yKuu%D7$?R|oPI%e^svn*) z*CTs#X;P`m-l-_BXj@ndOTnN{iN`*{*T6BB3B!bp|Kt}yteb(i6s`o}qw zVvi0MihbD66K&>JXXSbpdWxGwEbNNYv*{if*|7GH@*Df^+z)46T-V>RT&XO&62dVs zn+MLj;vKG63crTats2$f*E@T|ja@6UP(Gq+H)ZITF7(QO$SK4dh3w@nzt6+Tf#W7{ zX;NCMu67p<(bgGKbxE^g%ElX3*O630RB1;aEqU8Wu8h+!Hk%sf4@E>A&MFztOs>;d zZ|a#yG7(3xLaX>&KWB&pJd(PR5p>QY8u$-!`{Z-^i@((B+sjT$ASWzIPPdz+R`stJ zk~pSzhOp7;kHCGmU|Dz)AW;$=nKBCe?eD@s5Jeue`HAlo8JL#mG%e&IhBrEmz{{9V z98UqcV|r-p_)z9W99zNi3HN0_-?VL5EoIJloi9o@rf@5dB|$VNW&vuVM3{#bc!7a0pOLFzIr zN*j2(8a75)ZmfGj)(0u>u)?1vfVtIsu`uz{c`vuhGF zCp)+u5VoX9*{>aN&tvt`h|@F_ieg*$^wwojvGRp#LOVIZ8(nja=k4shAhx%k@*0_-I2NpV~ObK5Q$@~Kv^L^Z1WnMAB= z0|{_1z{j6@K=%XE4v;=!qg28=h;k`hi3Vgdk4PdwE9ar65by!s5N< zm7uJ9NCt`^fQ53T6r{(Rp^1Y~d}X%ukqgz6Tr&`-Z1a+^l%qI>c}$rwcs0m?b6c2^ zDDKA_Vc_V@;)ToV+rRsH{f-wAZQU?=AkP>{$f04k6-nuH!Cms2#%XHeaT#0(Ao|Jg z8K)c-mjWQMGhekjho5&4BFVhz^ea#4tnubaRH9mx$WO)xAd`{v)H?8KSZ#D4%l=dv zpjbVNR62^W(UZGRUxgn^Q?PIcs2%JifMJVHe;uz899WfJ*{%8jR47ltSZ_QkZU5KPut;8-f9Ljn z!B~8+*aG1mF!Qj!^GHQS47fW@`p=nZ>KfUzIS;mr-|XU*g{w+Gu`(=Gasqbq?)|Z) zq|~V%!T}GTqJ@QTdRVHZTVb?v&+oy!5gj3H49P{aH_RU!WfIo769ITGpEOQcyXsy) z^p!_wg?^3VBLmk1-Ut{f?!q}F&{{yWudtAae5=AtK@P+LDZ-=E?fwA9R+(N9f`Xf&CmaP|t!GLno%?1eb@yjYH`d#B(TaH-gFJ(MYz+;+3w5&}Xw%c1XAZ`)Qk_2Sryfc-GSJguSQD(xi?+|o7zY@XLH;cL{uveDnKZYq1_(l4ZJ zJN(`8HKN4(ppef1TVZM+SsBX)y+EBugU?zt1wMC;0sXwAK4m){*LiDeHWFKCR^YGmQYla30oWo#}$R>>_I!++}g2j74$ zD%bcgitN9D=>K++&H7i7&G2`~!2jDb{(n~1|8(sAM=I;TKh*z?g2wPa*;1G*puqc`-JqpCyfo zW;o)44W8ks#<12OC`~zx7K_Z#koqaR)c%u%FcHIOLmuXvsq;g;QfIC~L!w?jEe!^#1 z19RVri1dy!sazkvT(zO-o&P5F-FOMR;p_34K=Kc(`%p^P%7AWfvNwt4l<hRx)>{ zOzFwr+!;YsonrHMwgRNPeLA`X3r=8IvjeBltguo!tWr83?sig7i!PkX;CqAgT$9-4>_J1?@Z06V-#EL5*S#GKj_j zZCNDuRybQG{?^gj2d`&<14Il$ZSQ*uP6=DhH?lcg`a?E!W`r0prO+c>O!)iL}@Ns7M}pYQqzEA$8h?IRh3t@8-a%- z^;=(~8Fk~b3#;ji>DALvzom(O+wpM2@E55aG_OCwiV<03q^Jv^v>)dLKGNK@{R({m zl*wv9_Fkk5xDsf)xS;v1{B0n0TpWVOI{P#!)p^ZoJ6EEix4M7?u7Jo;{e%4TGSw#- zA~faA9Nv2&_bbQqEPNMy{#@P8o3!U5sqyipjvrS zz4IdQ!n&UOJuFYQnN$Wh_;n;)l_mS0+uDssd4>W}JW2_2sCaag)t+mUOm(xJ@3^R^ zT{fu<8B`)CBER{N=i|C!r%#m$S2ng3W-B~H;?hqODk6!#k@M!(b0Dyd>K|4-Ubox=T^?16svbK>FzybNsJHS4(;q8at zmN>|??wt2&cESB%YM+GFBRYU+3Bm#Qu+?i@mzOk(Gfm_1hI2@VjHEwH+#4Yg7i$So z=BR$&AxsCchmiJ!emuoNX4+-LS&(Y=UJ^co_FcwP`H9HOk*Lw@OuV8pZbj`)dW=F^m8(3zw#Hkv7RKs#*4qxDEW&Mx|0m(GpnoE zo_^IqR|Z$1Zvu?``L1>G@Q2~Fe8Pmx%=4U4vfy$JzGr>40L-Y64891|sE4(E$tz)d z9%|i>7*>qQnhh37;Rd@-h1Cl2QEz{18g1%7<9Xb8OE z&Lqt!G|Eze-K3D@xFPal{rWED{J8y~4W| z5M>5lW1akdTH7zTb9mVXT|j|tIM&_m7Q99nOFuIPk9b+At1)a6oLMX1+uW+@O166- z>hQ!W;YJzo$?O3>@fBXeTpr`LaUhrn#c+mup?SbF)0IT~6ZgOHzmvm50giYIe7Be% z^i-hg#urFlV|L;4;?7Tx5kTzvph*EPn`$-KNW~>`wo9t2@JH%qMR+<Xm(P-~T$=?ytUkA>X=9;YF9MFE3d(T;Bik&z z!Cl_e>*b!3H1!IQ7NiDde2|qpr&PX03KP=K9U~ZOfi8{}dFZ11oxE4)o;W4O#-jJdoV= zM(M3G*4-`WaJ!NM)DJsu3DIl$E9A!=V@73%HBom%SlTYOTIdB{vVm;JTAalsPo(iJ z1i9`h4vHc8X>$|FNn1pQ(ud9|SK(_CG57|1-ln>2J+ucBHQy-M&~PT9YBPF6R!=4A#{NgAHw~ zE?0KuQ2shIQ8Z!32c(hr3tN*?G`6}dO8&~cpVKg*Gu%vG_u!t-S5qgks<~+++dVxm z5AoUVR*s} z_xX7u{j5nehz-UUPN2b??&i=P$JywJS8RvAY_v*7u@b%uq~bP>R7k;E-i%jjV2P;* z5`~@OQq%66Mno@f%NhL$u|BDM@_DFQtPiSQfe$_Z7i?6 z;&`p^>1(;@Y@|f(H$R5@+x@KigJDEU4JY;*`Z4ut{9vnd&YO)7IAMza{}iC}6IJ2aAKy zsv)*w=65QrT`Bax@9@W8U+vR_2d`s!e09{?6-Wk0L4-L(uhljY zUjDs>V1M*XhQwY`cqJsMh~$ScL_ag3{kfdcsg+-DAGgU}}lmnVrC1r8X|Ht~(aL=&5l!}{ZedsgRXvDBQ=RL+um zAATMwOldlp*HkhYc^M8EKozFTr4+>qQ?ezfA>HpJrW7SC5no$>DD;9je~#RuqiTSk zv_Y*dWQHd*jnyFVgbe7qN6#mf<(boNTZL@aIyUu7g?)O(0%!I`!MM~a#aAtw%~OLe zvR3R_<~xyyeLQLktU$+PjR2H|%6kN(L;!V-YuxU;bMWp6fB2$A$0G#rKx@KYf`%Vm z!`0;BGC0W?dyUP|U@Ia9B9V=RfKZ99MxJ zC*mY2J_Np@yK7mzeVG(4rN9s!$w9P{cw?KmZ%#47y|jJWUoTpAeB0jGtsUVae@V;U z_a>hAo-*OOV}!V5^Q1e$HHC3(0_mKo*<+02nvc?gn+aWnHJdx~i4YgGiQTw`31nMG z5RcGvKiZ=k@E6Mt>a7>K6-(xUZ{}IW>}0@Ve=9|QGw@=vyfZB7{c!F0le0e|g7HcL$Qkym+ssh3l!{L_P&E1hDxoQI5so8Q&YgGfti4YBp0`eyB z9%*(MZ%AJ(Dw;7q^vxYPMK8KfickM23I?jbdDPzrlK1=JCZ(A!F20^9XXN}4g*yvX zI0D%@kWt8VD082OJ%*PW*?6k=&w!wRszX{tfcsA{m?ki zQpr2H$8uaPKw3l5R#%p+}S-uj@e~-xU#|mq zxoj_Iu@#o7m-XDHjebs7zNe+Vx$}dFg9RR`Y;)V!k1Ujy~WgQ^G#q1uc zu>S_0*yo!zN1vgzE8A^q9X}7U`y8}gbVy`?01ws2uUxri3od+Owu>4{^Tj+6;Ven1 z!d^C3nVn%AEbMjt0}v>=BXU;YCz;D9taWg}97b1rXD2s^DBcfvjUEEZZrE{F^(`_R z2vHz#ee?*F_v|r8-YG1L4CAh{q!j<-H|6cw5f*q?dI?Gf^8rqtJkU4VVm#JUxYRuD@yb#x6d1m~(cm@hnQ z%z`i`#e0w*>=HaKY_mK&#onrJyeB35_{B9Sb{}83bmMYwNAN+kISw_-3oTw!0+)O($+qby19wFV^HK!+DYL_(f-~d2tEd4x=8N z`E5!-pGhmDCTXonJx}xj81$l)!umPYR*9$XVHCW+CMfvQ#lSQn!9y!9Ir(F#k^)G7 z6qh>FvQNLh3y9;a%P3F};h7*Ya=f$iTYgIFJZaCifCf(wfh z2}s9xH~}yqzaa49RM)Wh^`W?9^5mCh!c%2GWqz|c7^c;6+$twChwZZfS^!moX2`5n zxFD4va*7P0pdD2l>x!7>SGX!5gT_#o;K&*OG?qWzA!dSf5QQ{7{HweOY!iiRLCs&O z-lR#OBnt>kQ0c+>-w7oxB;=)b)()1gp~;xC?Zm78;lAlmJ`FbSN5>$FuQd!yvpqw& zn>)WwFBU)^E7O<3L5>ttUn`A)ng|0dam~8|KD<1*%DA|zJteG5Ta$9QFRyPyUO3$I z+W{~!tzTa=@840w3kkCXB*>|9&PigQM^Mt-xb3{7+UMG1+UPtl)K0zxhOGQgKKmR3 z{c>a4T}N?(SOxj#g{u4@GeHyF(+P|qPJhnPf?Y0x(q+HOEpLv&)Fc5>w!A_dp^QM0lW(_0>7!Tlj zlxkY|ZB|8Zjq`H@GkNR_tJ}W)Y`%nu7fc=Z&e=f$i_9iL&yuw+3L>|9D-#!fA80O` z@s>E8PM(99lsjo%3u@G)ymkw3onZt6wdRHhd4g8rZ+e7AfA`xE>2tt&4IL3`u6UtX%Xrh4x!5AI znu?ZjG$YQxtx~0-2JjI?YW5i;QK8BrssChK4}SxT4Cy|DPQL8dZuuaSM7*d1naRVh z8_JH($e-!}O%;}Jd(>E8nWw*uyteFNU;U{hkprl|zqy2oH0d=!W2iZ*w&QL~F;Ts? z(8n#yohM)dmr-~YKt6iNGUeHnrRA*OuCDt+7S$r zC||(0Cu8eit#9@BORC1^re;p~%>TqAbFlwqSpB~$`&ilV zX&C=F)7k%+5*g_KCL#R)SJ_9y!19-YgyApt&A%P9*#BG1`Ul7O|I_f!eSed$}6$L=0p5V{7vzqXn{Wjmt+u zQ}z9TZt93^*@&#TWJOT0dPckGg%7|-*~sRXEH-%0UXHLPGxF>C&abhS#Pj)8ijk&* z8V1{>K+>#B=kpv=yhh_p@yKQCab1q`apGrKB3=lk(9<wChIXr+u=!^tS4w zzW0XGpN3{WueY}Nk@o%GWo=1+j@PGIpmfp0fzrA(*W7Pmot?-f&fBX~LeQ3O!-f2k zT&%gpb-`^RPUIgQb~qtEQZ6+`bcS8V>W_#1VNnRm-kyRD&yT2l)^t8^Vs-79`()N1 z)BQhgD6Fmy{D{wnWefNTiF4Gfzd4#}GB#Cr2pn8Tk7HJeeM%n?dmPbq_i(X=a8^Ke z_KAWsZQXuXXnuLpyC%YW99J|wAkcVKs*ZOYU6q^c=n=NK5kVRF;U|38mR~|B zV8x!`Y0Q?b}X+qxPrCWmFl)J|WwhKYP|Ipj`EO z+t^U>vTT-{XN6WIKRgT#lZ#h|3Y8&G?H=&BH=O@eeaa`RFp%wSv34xKmG|nSV|!if zq~V&*lw9><*T=Vo))B>7F;n_nb6Ld6w{L^u@swXzL-ANp$FAs&O`J3luHqT4!w;Pj z4OJLvdrigjJp)OnepA%EfRMZT)yMEwi^fTJ`t<-WU@P^Jt?VyUY-Cg&t$w3}V!rW~ zsetkepI)9Ig#%)nB(umBh(Go@CMeBc1f0tCW|&?Uog+c7Sfff2-YOZHGc24Lw#X1u z0tZ%HQpihof<8tsgxm^SCaJrI*L9F|hYC(xmcB#ZRUxjAevq6f;`WLJu=m52}wHEP_N1n@|u5F+a!@tPhdqErz*e@1Y zLjkQPPQPFnwBm;p8!M=DYnr9O1dCI>o2P99(=s=5psCp*a>+y4vAl_F`vZq3Offq^ zXq`v`t8oyq38qn&A=VT#hbz*8nL(`GoTUDm$o(P8Qc&tXV8>wAeBFvg`6!HQ?TX=5 ztIOuH#(J$Mg7+_Il>R5Z%9G%#<_7wk5Y?P|TfcCoI7DVQsR>B$3x4LM_mAOdnNx5?hyk7U1qPIv0-SmYzNr>D9&Kwc)1( z4ZEsDA8J4(WjtC|gf=Q5Y75`Psc=JVcWBt{9)rR~F~*&n%=w>j+jiV>Np9Gu38Ke* zv<$~SVt;)#P17WA2fCzNQ{gx8Iv)b%VvBTo2jWWj%sZ2`3l~smF#z66)UwJNp3G$c z7e`vkajpcopBU5Gf$HSuZH;W3M=*Q@opB-NwHq96 zP$s)ymI@j-3+DM}KpdKzn;g<|hq!CuxW`l{&!WWH6TJ33%7=-)^xrZU^!j*Ka^kG5 zG>(w*qCAHAKy{4xPY{Ba0GF5Xu8!7WWH67JtOi5hTD*N1(bn;yRF}OQg)g@?OPy5t zn86*fx+EQ;Zx+tUr4v#G5YYsPLOIXgI~xwtpnVwoS5WODpQ~`kwTNt-&+nbD=>bHl zKJ#3cyT*jL z{4Oc0`uQ+kFb^7Lj+4cKQ%UN4qt}(#6LD0d)IFKy#c06c4|0{~4Zh{+sj(|fk(>T* zer&2vn$L`Xmo#x!bG(q-$I;@NfM`8VaJi9?=r!As%Z`z}T+9JnX0m4Ka4#NhG0(?( z7F$E`shI8BKW3EuPT}A?lrVn8tEX{QXTFBpTLi^I%1@nK*YS z&3!2S`!0kJ_Yj7r;2G=7MdN3N%yh^d*7{QyR~-?bH|npa&FAP~euQ60rN*T++zyMo z^<$zj9Ar|83JqfF&`ngs89qC4@Rr^BbmO*Umt07h-7k+aJ$Esj-HSD!d@tFan)<&& z;d^7BDdA~Vdh@`B$d_rw`v>tENXiW2N&}hvM$$|Ti!q#{K9mn`=6BPpSW zD%O@}0>XpA)D83>9A@VQnR8nWyRkn-s`8PdIrt{R3!0%~7|i4zWE3U;IA7M6)B1^t_e5l51cyP*gVLto zP&bMmz&cv}4Pv<3KbMULbIgj(u^1)pW`?B;1K)Jxkq((Tj+9^|RzTt=)uWZ8sGx)y zNI8$FoRx|)@FPUSG1a`?C{7MN0#@?6+rD-$ZV5){2$Hrt-4p^~&MZn* zRP0*2|Ha%p0Lj+8YreZ}yLxd$ZDXI$Ao*D|gXzoPf~eJc}4=?|Sy5$x3)? z$9jWKiQFUV936NVMG#Vde4o7~#UQL9amG#;Xhd=rxNmJHw6Ub}GQw-~6yknf&))j# znBs48`wsUx;Fx=;dhwB)DX%Ga@Fg-AV(_En(JP_>VBLGo=BXa(9hywJe!0VSEXwQ1 z(MX0TWNgGq3-G(vJuTdA%T(x%P+e!x+$e)lebsomL z+VD}5Q1P9-qy%zR)=OtZZIH@xrrv*#(k|S_D!2>8KNe-tZC;P zW?G^ZthJdgPK77Mrj1HulT&CB(98*MUY^9v@9F)3MEux3S00z@=Y@Vx{59@Nx@uwK zzW+NmPQuYNVTUc@4XteHk@K^+ss@%S83~em*=lm&=AQn=__sx9NLrv?~BLg_VA2z{ZG;x8$@lP_07 z&lz8dT0GH|J;rW~DkUemPCN-Ou5ma~7-xaNt2C=Igat_~{M-BMp7CR;V;a*c*aurO zh*~7e%s20)%T3Ohom^H+SamdJvl{)+p2QZW{idxl?QGNip8m`_Sw027X8(Y5z4?|m z1nyKFlRL_|iroztb9^X@;#+PT4?qw?S^r(S!gm7}8 zd`t*Ic`-7?t|gGpqm`4|W69fKjeAs$2}x2>l}((Zba&q*YFG|gxyMGXz9ukq?FB@HB>guE zQquZcL3W-g-^cEmkUHJD*Q($)IRVk=;ab-UhbE%qAO_oyFu16e?kuzN5@krJ z&CvcG3$64Fkk629!8QnxCjW^?Bg< zCbVx^b$nD)m>u+Kh5CC>kx|8)o>(q?U_J2y|FH_~_au@UbQh(=u_M$4nM%uGn%vG= zRIrN7A1G)hrV2(T7)4iQYI?dGALG|+413z-)oIuUL1<@=FTnV^%zD3GO&F-R5nLSbxTYBE4phFnG&Jq~AXQ>(e%MAmVG< zctWCHa9R83e(9BZb`0`ejy08|vgiDmy)nPlx>%Vt$7H?__JO9OP*AsmJ>%xRm(?Q- z4?79=+ghw?_tjJ(M++iw>QV3bGmX7UM1ZZd3(n#aYCd=`RgUTG(IaD_RJPu)lRIdDY7&Ub< z_35NyI96d#;-i~KqY81>tNG-Yh%+f#$)zh;Q~CGMGi@I%`#r-HbXT{Tv~e^SgpOyA zOS_`bIx3vYe3HA@^3tY=0TQ!Mgry@_gobAf3IDw@MjlE3g;xVs52)Kkq9l&$0@L9IDhFd0q z3>$$k99)QXhUm|>8BrLIilthKr{0wcK=nf*m#31`S@MQ?0@-ndBDDmDkZy+bc@jg? zw=M+|5?p26_hGm4v2Q$YQ(0MPCl4)Z*55l7rzD;MovB{+#E5_5-b}T;?EZ!Sd`>X`1sDC%CVo= zMoEn)8q8Zkoz(w4if*VATn%Am(|}Gt?oxpQ`Of<+>%~S*&4Fc76B~3`Y5j7^%jq%Q zbk^6B&<5X+x`X{!+Ns)H!i~ch!UPE$Pc+ngsQD_W`Fv_h?!w60LH=QDzH(^_*x0VD zei2|RVGCvQ6QR@{ot$DJ?r?IV_>(OO63^}U9a9xlQL- z2_3J_;HbggATFogcdCfz<|^N@r+O7j9eR+X5V4&UWF?MT2ond3(`T*|Nr@3P{wg)# zQuwSFAN5q>Afr+j#TgF*S)U1Hax5mMb1pEp$V`WE6bBmMtg4xaeWc84GG0r+-U6rX z_tFjexaAw|gbAd#xwSTTab4 zeL_cKatUTy?Jm+TsBu0+%Krn3$2P1X2+h zc!rIE!hxN&(t%%{q#{@q)H7Ug+l#HGeWnGfE8{XaeoCe(bE|P#*ah@fI8x{+3^@5HEIfLH1w+`Y^T-+z7_i^O0Q3z%{6FH^!mqW#y*eIy= zti)BhoZ<(Ho`aOhokDNk* zdbrSnd6HxxcNGMX#Xi6jiz>~dk?&*iYn&4k%)MP+^IdE%Xp!PE+R`J%QV0mLLPu?< z-X4u&AL$k-jfRW_>)9;Q0RTyv3ZV8`W8M_dtX?giQH5z~2>J4n#sKq=K6oVk^3;kW zz!pG-^fGdM^z0+m?3bC({M;dT0LxC*78;sN7OPAaepAYF-qx@kj4twr(q*LScpi~pu|2{Jx3{qMhY$)U z7E@XRc_P{soXs|+LX)6a?#|EM1()_E((ium5C6{wXOnbP>8sc7ALYJyH zvnK^00{D-^4_cV?N2tejCEztYykF&%2R~?fW4Fp5J*N!#n$oIE&d9+{qtA2Hg*%FmCCR z^{`s8!aW;6Hu9GiP(?}9<#?YH%c@Qs=AOiP+LM=dx-*h{A^mCL1-*ykTT+pmb)q{H zKLz027Ws3#tL60>6DnfV`C&(CS2tOZmiKmtoio$A>vhL*qT17@CzVz4enL>6Z`71e z_z>V&)~oO(0RuVWL2PVuVBBL7?l`6RA6W$OGb7qsP&hsEWknKtd5TYK&x>AQq1E-& zO9Pvu=*%dK%x0ieH^R9?`O1Xwx)G(Wr2aq!z;mk{VyZ-B^t&Ao^=0s%>TEw)VE>gpQy*b%tHT%B+vgl({cZ}mi|LbF)}gzH)3jESu%S4 zTTD$?9}{4RGIk4L2EjF?~ShgEx%Kl2XJ2#bHK&oXJ<0wTqDv8V`@+iBikO zZ=RQ3x;>mOhHEdDE7N$nzI|riE}ku0Z*?lNbg^#$pO#o@y}x5cwx_eKr=zV`Rs%M6 z7Oq}oEm?KXMXx!LU*CLTSF5>QzsCf1{W|Dcn<0f-d>oI=-?-qh@><(^zlTzFrBi{8 zIQT7)bp-|iEqR`H*ovk*znz)w{y+vTzo>`;I&1zKx*3_D_Etva#$ungB!9Wx?44PM zEw!G-kZ##Q`RG5mC&*)yA$cm4d;Zpb*L->_Se@mV_v}g{u1|B9%_>Xpj?ZJn`p2R- zBarYmZ-r&HEFqo!(1kT25`*|2;%*SB$ev`OC&LaO7Cdlw;GB*n{;ldIBb3dU)fn%# zbA)C1z3}+S8F6qsjK&I{HIbZsar@@xtiHo6+TA&mox>TMO;h_;apo(^*c41+OINN6 zY4VBVRE2}r&QcTHu`k{-5xe<)uv|nH`>j&z&OhU^!qJYE}b0uI*S8J?24QV^} z(qj#a_t)wjyfC-i)Ihj$HqGILmz}n^e@5s-V0*26OYWUZ0l=pAe#Yj5urOk9)2Zn< z%}wfzSSk`gC}3+-S7r8OQS8bO1k5Wu*6jEQHM--Sf{W>=Fy^(F#X)_=6=z`UQ%VO5 z)V1mn=+y65V*-l6NM)7Q?(#?PnSR(`4KABCvRc3ItdF}*uVocy!qRxiYg>Y}Ro(*m z)pbB%zdGZjhqo8+dZFK6EYeyY2&H?_#%G~X(Kiu;ctp^}Q2lA+@M>6y zgD`&9`V4(}@f!bLwjYWN4K>qItKrxI2^*@4c%gL2gFTnf&=hI~c49RK*nZs)Ew zfGDSLF6)P?@jpzJs%B-Z@7|9pl4|2{&k=c6J6SHy)+$+)Sxz~&p1oQZhb?#fOz)s< z$h|7O8Cqa@i8)*HY|Q&(Aoq)G+evXaIDNqjjV`-)wUwBX%KvM zWj?gFu_=gQs5a$Yx|U{f@98^d9Jm-RyPe9WU8!hG(YYoBG;w-bIKwJM@NY=DbW7i^ zLdxk0s+-({o{?+BqU)gnpFd*j+2C8O(~Ii2j_0@rcyA;5htPa3aK{<$gKK0C-1YK| zn*DpziF%&;EL>FAdl6}w2g8(4x17qMIKBk+hEW-_Mc#S0rVO^f{D|%G3aJoXmH|ZI zGB|`e)uVEf^UDPB>J3Xx&_eKuvvQvLn5`!TEzcDy6hL%C=N&(L5JjIbI-o~Hy=?-0p0Ex`h5XD)c_0-i zCBTL83-)RlJ<;ub!MN}|ac|pqPm8x`>Jo4{l~DlcABHztd)1B?U} zHToIYs!N4u=A#z&$A7@`l9Qp&n;FBOHdo)kAJr%G0E1kx={Ofb>XY^Q(u*XsvK35o2#kH zQp!_ezUf!vyIp8!f}hJ(yAUJj2Xc^!YID_lDMZmVTBXH z314CE`PFx{xlJyPSa3yZ!2y7cuHXQ)Dx1O7A{YGfsYYI_kT`+kfN221D2ehi+s?6XKqqvjiRDLE3=URo4E9fQqu7rzZ)hFA|MXg zk7n|k>KR{N*ft5&q$cPTc;tFH)`_s;u2vN?;h9lr#>3blpe&x>dyDnhR`yP%b#i3WEs`%LL+Kv{y9u(P?3oqK0_p^wX zMHvA*A3jiN*>6EEF;0mdMU^QsGdkk$(9=i|^h409(GJEghM5iL=MLwZ<$}bA2}u_j zXSI2A5dlAzMPw9yyi zq9%P~kiMBNC3hi#qe~MxmvFx)fyV;TO2}2C!E@qU3r4M-MGAqjlQCnLE`6Pol>bv7k@9)=bNW8zDxFBFe{9R~mb)I4+ zT^kddn4td9Qp{+6RgMyoj4#rdo5Ufq-b-7ckK3l}gv&@XGMY+!Zi*c2dTNNlY6daL zz=c4~RhQgV0o6wdaABlWG32jupbiSezIlP*FR~#)R;woj4~2T+V7lOD?F27AMV!y# zqeRL?=oQHp@{zd2!kXuA(Gl5AM@dyc{YfVz&qNAS1u?IC)3bKWiV``4{YwR)nhR?a0QjtH8bKzycL_jgEK#G+8B zB*wIG*q?cCMS?G^HI~<%OUeS|sk(zh$~3E~EQn!TB3M{|k{$4X1?=H_Tp61}0jP}M zh8ZwtUhwHYMMK2np#TZ@vf+(jQvk+8nJCP-ma*Whu5GBb6K(i9`-zl1zEa99NwcPG zi{x}XH7)JHR?vTjkDO@H9QNS$A3)~f+$x) zzm+66c5vDo%VlsrnBxi1-xQuwc>Q5W(F%qo{*~ASfmxfYNGNM0J9^K&Nif?*(fHS& zAsc1G22YAfxj&4YexVC56YGpkB68|Vcp{hE;wQNwI~+otNsc4Urih~baqhAfLXy>& z>qVSb6k{6;f<$g5kDl{oU0lm=yV)7a<5qpN@b4%%rGf;vIe^?i4^a}fxQKQI12U!B z+o=x()IzaqK;nK>)fbzonYLLttdFH&>#Oy11SIX@qp;kIkfo8A^I&-crkFUD3`59| zpdUV#u$#laXRIS61HK-0b?2ot32Rse15x7TG(hmMou_Iz@Pyv!_uCGvJ3eLPO6xAn z0i`a+GM@f@M58j3P)-p<5WN)snD^8b4r_sDXM)6cyHY) z{4q|!5E!o&3H_RhhdRWk7sU1DY-CYjpy61XO6OoE6#Z+6vD!~$M_>kOM8P(7d3I@;=}pzc0s2~ucM@J@KaAdn@$`HDd5_95y>O}6dVY$`JL7d&;~|Qiuw~EV z0_sCA9V8;F;hC`m=>#9xde*lBpKV6*pDa+QIk$O$@d=SoVWn(i9el)fb$`-?q8`@2B|wts(ydZ-RlD>Ayp{ohwUPuZtpfzI{*eK~e^7<45-X*ds)8p&JDb zg#{pn@=qd7#Y$xq9ZR}BYt~Y9j-L~UUJBow|0T$j{voURuvLD#oV`HP-SK&ScvyM6 zP~EN7?U_%_+1PchSW2zc{l$Orxa;P1bqHT}TJqjU!%nZh$KFsXjv{`}=z z6{Mv>lT%czo?2|QAP&Uj-SRx1x*WgKx;dw>D1~pVEFouHN*sDe1&$~b9mB44?<$~u zHoD+^8>M!SCzp9bzt`lF>*yg(6QE12B+t?yDAYYnWz?vAFT)07N^2;Iv%q59*gK)d zobsois7UWf50RDPe*5-R#WWOP5LVvaYnU4b*7xA@CXpluFFvWpbU4_4<)?j`W&GXJ zHu3ZGkumzRULnpP6^uoglH@1%7nb|__{zEo(e7>O6+W=_X!`aD2!bnbwikcA=0oUo z=rB-aRJ?=Gd|A=Z)I9+QAUjMtChLWPuv73<7CZC3b_s=}=5jiI^}ub_s-EK>E;~1> zn;y{j7~i%EdQBj}YBC`7@46ZjrS#WSr##%6@JFmppf=_PHp_sb&55jyqxd^it$;uX z;d;h83Tb-!FoLF*;c>r;FRyT=c^Mj?B~sXTCLj_gvq$#q3AHQLGtVY3%vY-B`P_sPfQr-!<`@&+si(Ybd~#I1El?JtAvaDw&ATn`=sodQLwao7yx zlN*%d3iQ7>XnkJb(DplDc%&+^Gc?@S+R-X$G1rMhHx}Y8d9@)8BV-VH;G5!LTLhGS zkEs(2Z^j0ihn72#K<}Wutsfk+OUhlLlDBf2-8S?zmbFSdRL7B5t@4%YadU;JMCrMO zK`Up`0l1BH7|)@4k5e!%kl1FM2_#1XQe2c_yw$gzpYwfdjl80hM)HW}rNWI;1NWoO zD{f)mnKy{_kjg{new?Z*NefKFjI0Njyz#Vth3`jwp>4ow_gyFu0SCu~u#H_Db2ih- zXLDe$4@qw_`h77qr{iz`B;Et=fC_bHW8&~jKcw>>w8^y+OE7H1C(-LmyQ8q9m?2_I ztugQ4UWON3No8U1wYIZ!A?;amZHYaXWL5D1^9E1>1Q7ZO2LM1d&050d>i=u8Fbbau zgX-QrC*%Mfuhq#1hpU<$XY|>FaN2b_oi8VU7MJ+T7JiR1i1&$)vb;(KjTru@ZxsfJ zOdeB{`(eM?3@v0W(CTLpu|kZO5z7KQy&07w%DC75eg&kUK^T|FQamTXWSgJKYzmdw zO~S)i3Haoe{D$i9v^2Epr1#Es9@OLj;06eo4P{2j%|8jsogJ?XP}QZ(ZY34NGHf^x ztKHZSE~qkqer3^uTwI+Mu#K~WHk7BKS3vYH2_^HWLR+GPD4?m&lwNkp(0j~6{P22v&!T|-9MKLc#jRCVkv zPKV5>#yMuSOm+rwHBqg&y$CwT4RWE>DJDqGj5c^@NQ~}B2BbqO$yo1w5;kiQn9f=! z5#3Ye`SBUe&3 z)&wVL@H?Au4n+u2g*8N?7nx8=j&_UG5z-{SqLH6OB&E$&uovf6x4mz~{Ew4e%+2lUg)>$2r-> z8|iIO*v`F3P0&0_pHl-RN6}{I`|IN)0v#n!s}`rj4S3Uoo5tG#nJnG}VGWloh)s52j`+#WKI)q(ga!R~|v+WDgBifZ#>G#Uvp zB=nNg%6tK8XqqYsY}AnP=5Kt%*dC|Wil5P=9xZHdA6r;+$H}O%R-n+LCN@lDq3736 zux4%PJoFII!b^Be3#edPq<96Uh9B}3r+ZEXMowRn<7wE*+DrgsHl5e(G;=j66ZiM1 zHZ==@r0I8B0}_TpDrkMzCQ|F%XSzSwo@~LDxOWL`z+(5F|k|BxYC*@)oT=b1iMX%K7?hZ)j_Le}b z^%4ekejcyZjUcy+C=sOuPFs9aPfwxt+$_0Q`y1x8YhytN2oUM*G%*rmX!AICzXS!O zwAEO}#c+tcEpW=Z`T`IU%SS{&t7VLAxc2bbxk~dV>FL&wcOB&eJIe^LM@(unyKRPkXH@D z#>J8m-0==drR?jq5d&y_APA*QYfSZzIS%Sg zf;-$c9mLTjS+px~tr5ZOj%t`4aBMvh1N_mVUvUgEwD$~&vW7$0gib*a{ngqT{2hJD z->AzGqliG}t_j0%R^dl|3Su% zGJ3qdGGblEQNuod>M6hFz{vOKTo}|%SD${rStMJA?jMw6iGI)ZFqRg}_K%?3pk2e$ z%9R0O=Qj~mwLA`?4o}QJ;jx&p%gk_$%FP2~H?unUxm4ay)=UVN)dw(DVy+4LQV15m zk&taY=#*N6jT8mN1F(i2$$bkvePL4C;?}%E|BC%$=0A4z1*Z;&>3Ll_=D}kumX-2T z@h*W<3rT=rhWNE zrmD!_9>^R7*Nkc6A8AAJE@oRAijQd0eLF3pG!gn({pyDE&aGEEp;ta~1mT6xf#cle zpnZ+KsR|#D_~n0d<~yBxJa!tDkzoXtFG6kYGZ`h>jFtci zY{SSC%CTOL`!Vcd&+1MejEKx(NJV6;g7x#w0gQup&Ibf{0lH`KHf!k$4hHb!31_t( z&DF}_xPtz+gTnk1iIjWU>?+@+e#a<^U3)t|>Hhlm95wQi#Gf*fVJx4$A;8~KwC|-* z(Wn?de8I=9&`V)SZtcwNHBgZ}I6b|=h|rxCtxfCqHL>f>=%sZU6dSsY^MENL^6q4^ za*WV+BgL0*Jgy>T1JVe&s|s?X%12*e)?lf=nV4XPRIujvTrV&vAr>W$qziCtH|0yy zp#`eCTSUg_JmE|5G@kV%9}=;E4w-PVQMWdpoW@=W)F0-cb6{2Tvam$-mHs6LxppVO z2VvDeN!AVx99v6;>DYaryQw{WAR`n~ah0Nyy#Yx5DgoKH3HO3U?KZgx9l0hg z5Hi)V(8dR$pt~jn&Im8zl*E@^b3poyJS%=#1p$W;Ab~ud_k)@&F6#W4JiH@ED9aC7 zluVSVU&79csu3P0j?x7JJRZongjHpZP`%tP@Y+i;E|r1#kuhk50`mjzpzoD5EsRw$J6nM{oXwsa}YtPwn6(BE+UZ z$RRDx6r5-hoJ@AG%c2j&VtHJrU`ZYsk7_8%rXsB9`(`I&rw%fXwgBJ8sXSwIO39oz zDeR>-V$8YG-9reBpzv15rm_&Xm3CX9?tZ}j+PZ8mF^64VN2BGuh4ou;;l`wvK%H&a zU;z!68)^k9qy_nND^vBIN!IF*)X?-pA`dPHZrmLOqogcizuQS!9A5l*Co`2#6fg0HVuF$B|P<_G86UEyhuGzsK-}4dgLTi4u)z^&j6* zuKIcGJz=o}Yh!dFX@Ds1i?Ytholy<+c`rHz$@JN})9`%9o@P+yD$pG}R)H8o3sz-9 z{l|4DTUG<>dftQQ295}MJ&N09AN)oXy89_0oa1*<6sc3|?R>4FjQ;3e(L{uIF;WBX z0I{}17-94Y*BtXC_8s(k`?!EUT(Z>QU<9!$jV8KkrLTGC{csQ}wYq6|^X#C@lI~u_)x&Dln=agj1UOQ80lh zX*qbIVu1X{$M{tLcP6X=us1a&s3shJI-$!%fkA9IPLolxS{)Zs?GnE8DRQ<@;gV*nf;y{OsS9$!%)a)TYa1@f ztWjwLTE4L@zt?QByl41}=Dy+dxc5%L?6s}&UQxJ`Q=vRPe0nOlvt2af6SCW}ef8&z zOtNl@UB70*)UX-rZmxMNMK{Gl(N1h&J9tK}RrC96O|t7X2Wgi16{wUp+ym7wa-wbK z#<%K4o^L(=6R?uB2g9!r%@BiGd+xKvor}{&ytVW$_c$!wtfWl~MKjP+c(IeRADcq; z<+O^rmCyWYCMT-)_b}O-TvXtq>&*=1rHG10uCg|;R?G-&%}5c&l0Oy))5pb0b!T2S z2WMhK(A9a(59XFD4G8Upy|ZLU?DjHehE;*%89t?Z!F5QopNs_+%z^0~!$EF(Fdg&$ zD4!1w;ET%dC$9kADOti6CZ$0vg7PTOUf*N9R{&RQVQvi_Y+<0EiN`@&9gNoKXHBdF zWVl{E00^{rkhT>{){^LHo^%?vw5OiouF1$hxI0MXJJdBh-XeS6-hq#Me!L=hc~Ua? zO)~!OBpsl(q9#Qy=NT@79xiUsQA>&6h@_4k(z+Z+%+CByE;M)pNh{o-?zVzk2euEu zDT9O1IhObbdlo^=Y8DqgZ#`&U20cJ0ifRkz@#jmD{V>Mrnp89Oyl?xw1lEbFIXvf# zGXEHu0eCsWq~6gG41PPpJ5MoyBO$SmwVQR~6!#h?K-|XwZ|pHI+yNt&lJ^(SXZ#n! z=d8BB_r5!Vh&Slx&2a*L(P}CFzWg(s9ZmGd%5L`H*YCv(7BD4SzD~st*}-CDIR&At z=8DqjM(urcO^93JcRIMGSj@eRT4w#UhbdxQz5T%0WW!c6K%W7oSMDEBg%XkEdF29B zr_ol9)n(o|7u;A(BW5ey7ca7tyPZ5+ERM1(JB4SuO$-_<-6Qt{uw~x(Z3=B={gZXd4o5BmC9cLi`1J z^>E~AkWLE&yyXxS^%&B3SD+y`L(JGlF>WG6or=Ii3;X$Lo*YdVkfEVL@C0Y1JJ>@J z7$SWIJdZ08qE#LxvvY-+*J1;0Ep#$OP~i}(uJZKhB}KgbXvBWG%bt_eXGq{oV`bRR z@sx{YG~?Ep3mQcd&L>T%Dn2>30F@2GVj4p!@8q8q-(Kj5Qs*8!YHx z@2pPk=GWK?B0gW!G?1EQgxjTz9@>4_ClCG8k(k_94s#<7BWIk$>Dh@AO8TrlTC6LE ziSQY?6(!V0aBc}^O^)`WE%y?Ds`4tGl5rs6W{=fnLf+|hDbz~GhEtx$2x;2+K{kv% zxa=IEkTzqJheVi0uztcebt|!`D?#SBqCP~N`o`3vjqfjl2GoEVlKbV@FO;%i0>h^h zEFbgRr=&#W(bO8WoC!v!7vTUePLQml(vBqcsZEE6|}wF<=ZYl#+%7lCMw zwif}B-|(DSJohfGNC>s9l0`}24AvOpJ8$Rjwn^(eO9B8Kh0oZssV)_Zs6=`GV?)=0 zIY?yQle~YDp+QTS-Mu+`er$;o_}?`v;x{N##*rtv1Dg_1T7ajEXGY*jqKEp`j{Al* zLi19YT*#7-$qmT`#&}{^kWmh*t5xm;>_VS`{!HQ`*(KQFd&6id+Kyes1u;D86sFaB zVJoc-w5!Wd>yPGJRVYr(fevg4CF-n)oJhloR|1+%FeoYF)K0e z;u-7owXT`b2yDlbBz4yE3nqU;G1qHvcILsXrLekD+h+G63PMEPt8J!Ser_EirtqYQ zxStZ-6EN}MtW`G~b9yPXSY7fl{Wd!Eu_j^Ry_nrj5|y_Wd5SB?>4L&DQ0qd%%l_hZ zu5;y`a19)}^*H56H{>oLMB?p0%c8N#c-noKS&(qX09%6QHgdbYkRVxB(#~IP@d0JQ z0e3pax=ZViS}|Xuv;TF|-*ljsM5v>RiPj-%`Y4xHiK9+eG4Us^S#k23IisSE!BpH% z)Q~&9$fjd~dkT@4rAsh_53|A0yV~@335ozo?z(JWK=ZB}zesV!ZtX1bNDRPFtRtZL zWe-_n=%UgFLfX*gI8`Yon1#~i=!qk2&~2stDLQ1hizGDa)jCNT40M^V!F_AoTb6j% z7cJP}?Hy_SwwR%vj&-==i%_bCPlenlzZgM&_YV|$XCYYTxQfLE_}0ZkZO;N0QNT7E zXuJt3%uYga&~@Jkz!t11Pv2;>$-0Uvwp1`ph97~q=SfeE_c58G7lS^1S`B@(MQhMz z+jPRGRPtUj-t^0Fxmyd0WTalhW(u@la7vt75+vq*%6LhSpr_J{qa$#lsE!KSPo9gm zAKe9c_drtEIrR8_5TeI+2`e`^&>$v1EdC6a6*mtD;j@--*oCiQm37-HJc%yJW$00* z<}n?=6_&eAIEUlJX&(wNIy${3&y(P=c-7Ow*taDH^&+um(lR}Qj-+PW&FTuHPQgiu zN@kRwWu;ctLYl|m0-jfvuA0;Wbh)WdJw!^po%3k}S6?SxS!HhgY_8e#Sj~W52uMzY zQAmsPbt9MA8`O%Zd}x%9fQ<)^LrCM*RGnW9Zz=*u7b@DstR^?~S<5yX0AWtXlAJBo zrRh>Rj3sMJi=>M71{K$?U&j{Q2lF~^fl}ae-ycvj7?iI#K(%l zN_r_7Mi8XVh;(C=ZEt)xcad6Jp@rmox&E2mF6)6w^&z-WVTrw~ls~&xiX=zH50beM z2lxu@+g>zG04BH02HBm^+#|}+iy0^28q+s*N!%kDIM?P6zODbqayG@6VK$oBW5nWK z0B4uhdoyAve2+zoMZg=vHiYPz$Jzbtp{fPZCV*Yo!z0MWwA%{v(tEi)_(K+&u+Yf5 z3vR9SQIf7F>K@4abk$%=lk0pc!hZy#9vKT3XgXRzz60{iwA|5Cp7B%%o2J9kypra! z;azYm{=OrLrmm9T60=_9a1uAWIoyAOFmqMW)6#=OIx{_E!J0Y~Tog2eFP;P1 zG}YNX-qfMRLHqW(6iH(F%>;IX4^=?zerfwpT3F}u%KN<@5)mpqoYYPlc_1IAtL@JM zVhw1$hf^?EDG?rb@l^Cy-~)+a1b{-5T7MPxF6ro7k!?;uB%WuD$D}ESz#sDhE#YKYtn<^5+Awr|niCjD{h412`OE~ok#8q$z z+>JIF)64S_wlraHk9FPTpHd%hKqz zI-m|AngPwDrtT1PfC_9EK0bPCMh__39~q!575_?k{e!>xcXdKf|KCjnD#X-UebbSG zoU?X^gt2=XMvQ8+dsGO!CUXE5Nr-hA|lPJbMKwqIQyJ?Fkybo}n|CQU&_ zx}Q?-BbzXQr)Fh^O9VcXSj&50&X4M0*r1m0tG)5`X)}6Hh?ma;(Q2zI(;9?*W>F

6%ldX5?-8Or#%l44r|54S~XDk+B+TJ0KnP{#0Zm0pOU z6Wcj)&vznmOFzhe)lvU&b>toO99(S-X%y@n4Hf<>{DnXgG_=>ZGqrKBw!@|WD~MT+ zMnc!#LBK@U?i;~MN26?N;9z2}PS5h!v46cVF#M$y|Ml{(j(J2 zUms;+`pdfd*ZW^}{I&k;bN(v-_4>Q5f9?Id^dI~GTGQe(u(JIRSNv1gcS)0mU)SF7 zuWq5?voqDTpyIc-F!+lVWoq~DeZoLbBV?s-ZD49;{M|QJd{*|R|GE92efkfjiT)pt z?cZ#wZvp*X`@dnS1O)^n1cWH$T`l#jE&ktuRNwwpL;CMq`EI-1za~^M{sX9@r(^rK zbNKnKUDRp6@l@X-0CaS841e*dnEsPb_1DI~ohGbnX=>q0`gaq^Xasa^ME}NL(bD|q z&HVF#(EQEL;1Z~T_7B@Co! z=!P&-k+8j9YlP!v$OzT!8?2gA7m6n6u$Dp zu;+rjrab%ySr3cprNR6&f5<^)q2=YVw#C;HrCIWvH#h}8b?50-d#CBFOt!Do)~Bz_ zkM6JTr$Z@tOg~(p7{mbIh~INMWXX`}Bm$EVz&m$}X`-X=U@RHeALI)s5if+`JR7Y) z_yC7+!NXH8MrxgMg6$CuL^%^Y?I{CS*HIU61Y=|%yVnEG>OVDjP()&`v1Fo{`2wqB zcKBm-OJ%%<4Ty|U3iS1J&w1h9k_W98;G%G#Jz=T^;nUX3vJY|?R2pYK(FcIix5Au7 z7h-Nkdf~rX`$IVnUw;LB`cr}T`EbIkO-phiXt8+Q#%6^t`?k40t!nKQ?)}DbpXWSg zvf5%QX_F|P9pFCx(PVrDojJ%qb7CO{oIX_0Dl%_6fytB>1^H?U$O20RA-L;qg`&p` zJ`kk>{}XQq{r4uR%OcLawd!Wy*~f3ew$SFiFl*njhn8#qs1S=8 zoHr3yo0FL8d<}8rrT)SjkuoNdoSi5Bub{3;BLiBt4qx^S)1?%93*NH{0@0j-QNVWl zA{Tf}UVs+PY_uN$Jr=^TDn3C^QUUj>X_c%qF>dAk7UKYz8>!aJyS$do@w>7m1!&m0 z3cd;wNg;)LYoolx$rN*qVT1tarqJOSFj|^G*z6-5MvUYrzh`DiJBoPegegN2zbHSi zta}=}zEbB^!2274v)tJ>5BR0Rd${H;d}a0_HwL#f$2X6zxK8|vsH#6)6rL{`qC2** z9{v~&GE@UpdcRyG@GyEml~^b{?)A;6+tYu9VAOX_!5nkPy^vN=+pD3}tD9U;JAg1B zC}qJ+MR2sA zzY{9mhCOIE`!GE&OvX*+)vM!J(VXi!R*H_mtYXsLjskFrxfvPCar3>_}`p zMPn^aT@Kzkp8ffiJg`1UFf*eyEbzq^iNBta=B)eaa!a7U0TV1o; zb}3<9x-9~7(W?sPLs#D+bLMQ!^DTt^Ds)~|PSG}8X|YW@W@X4yv(9_%u9K+pLJ?-L zS0yj|;Jz%AakEHZJ7j5?n{q3z^+ki$>!ZI-_3YDyn`rhv%SP(y7klIl1%zehR_p6i zc3L;9=6(om0JJ0^l5+s?Pofj)8XOVm)V5AWSSoq9NjI0`kRCJif2!}0#_BATshRA=C=UI@GEN_AG2bWGPKKW=w8{B+BWoLNWTRwR`p5_1$B*G5cIz(f+*4Y%tHq{&|qK$4q)fM-}7$ zY40loqI|l(LApDoB&6A0y1SL`&ZVS;rMndgk(Mqg>68$VRsoe11?f&n$#+5hoA-S` z&->mV-Vf}xz{S~_GiT16IXg4IGjpxBW6V#W9Fej_erW|py9k=gCN_9_x!4Rpa|c@l zHZGMWs@HW7B^8Vj(@ze)ug&I|EiiudM8c#fA?(#AD3o9V>)yoCVC}94OY!uisp0#i zo%I0W4zc}ufDA>$a1+bHQo!28_3E}yPR^vd4hj+T?biM!Q&#GZ`KUySGyuYw!7 z%p|s$a7dtWx}Mwgp?ak)39q)E^4SJP*SYwOXF9uxhZ^?~RcG4w`zWy=dl#M4x z><&9#>pcNE=i2uL^mmOn7>SwQI|de!(x*oX+)cqDf@x+&OOm@bhl4E*69{=6nVa`e zVvfXON*ec}D=d`)?~*`pqHm$6oZCty?J%~<9qPNx_B3s>J+u*U*0}hhEaKDDUp%X% z9Lkk%8}5zN!DiB%@i~lJk#*|cs21nJMw&tur%z7_!=nXlXrxZ`2D~9^)iPs(!L`1P zkDf!}Dyt)mNnpJ%c)c*}Da4{l6h;EsR5~jso0o)?q=OGNZGj9=j!W+D?c2L|Heep= zu!t($Kt7a^Y)y}_yzj4{HS!WjXZh%MNdjX{k~rKWV5Fc%XddGu|J%t!Wmx&9*2K2$ z)R-ZfrZ3~PGs(+fNJtTs>Dsk!56)uV>Y8IOxhATTqhaP`w_={zE1R16@J@iHRI(!k zl?(A)oAG!W6px!*40d9@sU<3~M5T~5BtAZbnDQ8Cau`RMg2rAP!ozMAm%iW-cjG@;vm41ZjF>wv(M@+y=JyTW(BgjQR9^0g5^l$HINN zk4u~3+H1X!-wYM@_PZW)FEsUjFg&m zM5OTD2DvOjtYeO-Ug^C`PXG5!jTMgWT}yYCKkR;RH8(rP=esUpk9;0>ScqXbuaWp6 zgYrQMB}8@MxPL2vJF4=_u}o1|&^1*mL~&7sw^Sj>Cy^n+k5E>&8>~F9-v$YVJubD9 zzjq5=Nmd8%tkGA7R8hj%x>@D4sJ8k2OUi)=k5nVJLKgNKKlK^l3p(m1wu6~awa4>O z9(>WC%U&PfZR;8sjpW}}dkfm<-_lok-5h*}wNFtbL`Rdp<+DzWPX}X}nAXN(u&u!< zG<YwRkO-urPW8f&0WxknD4VZ3f_#>^auvzjIqo-AkGDKzs;UzQa)pyzoh!ljL-pI$3?woDlH8UTp`b;c7D!3ZTUV0c?>NzpuznYrNyD7cfYEU-mbi#~EWX zx1th?vO-$<*ipQvn;bF3O;Ap;C%exCc@Y+;F?l73m4P>`sR+W2(QXH0lv7$b-xQ~F ze<2|RM~sPQjHwcU9B~78KSpl~lY%#lyk4BUWBNdR%}>l?8t)pec2x1EzmOy5*)@?? zhSayDkKgP8g3DS_nB^IAUs%_-3w%y#Lq?rqh!e*Uq#BvSwzgCXmd_G9M6%Hdz!($9 z*37^jL!{%~V9DFXe)yLDqqYa7+m@2a{To>H#8X}C=j#z ztc1ehvbRIwc_V02rZ7nSv$Ir>U@?X<38ejryG%n;BKE(Sb?Ra1loP1ni-S`A!{*>B zAL-vvTB0g?GTc-)rne@P*|4M6rr{oS2R-<%)w-!RMsLA0jM{d#A(pn9v*35IX&nh; zI9@Y~C$bdpB{5?YA?&B=&rO1oVN+gQ(*fQxV_l1<__UleQPO<#5Vg05POP79Nshkb z8FE4!>Af(l8yG`Y25j=em0F>yQQn$4-f(r(6!Of1!7{|of~Ii~*^4|3r8wTKXLqXTZXsldf3tvd)$J?L6mcKk;quG8MeUkk=IDSjCJ8JmwH z$m(Vw!pyc*S?Ej@?)`$1R^2%KIeQxFafIWC0_0xwS*Xvu7)qqhN7}foq`m915DZ(H zX=TC&k|Jm}@vhIgQQVc%3HOz!ww6?IlDqL)UyMnmKUVLa>H}mrD=GuASS!*AdAC8K zT}~mTls90s0MsEfQ-p zGPOa(hTxUKo7vN)xM;hr`q#YKHflw3LN;SoAvbkii}$L|DM?VvVy}U7-ow_ykREDh z8$YK-$Ny-57=Ml!=Z$%qsv;cb@<^*1T~nORU_yrp{!v>dRoD_vL=q$kO*0jR^X>bO z)~1RjRyBvbh1a|)?)6zX@1mEx+?$Z#An-)YC69ZGu(QbXxtO)~{u=tZrG+5JT{hmE zw2HU4lG^%jM&aSIJ$rVa{6jz|ZAwRgr@!4g?-P`4T3t2``7DUa%Mq3sE#|f&A{ULU zb$i!g3Z#P6;e>?}pZD~+)l5GAPS%w2Iwjgg_9z>EU5c``1?y&cQKxC=zGvt97X7d7 zn(7drxossoW}Jw5q7>`R`9%rmXU6LL>Y{FvaI(pdI4AaQbV83woArBm3M!mCLoU~D zSeiYlpWQdNtY6*2W)nJXbVMt4<}tw%=9)Q5+hLsa`qWC_XXyTdVD=QhYq2M|uDE#T zR(jNa?MQ;1UL7ZooxQE&Xyb~FQNdk)?!xQq;dT;xo_93z^0K`R-s?ISS}VxiRmrLl zO^^)ocPLS&RQJk8b&)QdQg_>caOgy4QP+y&_%ls&s$U%Y6T|#`~8jtZTp-^P9ROG;vvz8nnkdh*XGIF z#*o)3@4>@qHX1mOs?9_fx8o1lH+1DS`Wq=pNQuPna=s+Kj+v_UZf~b|l;b9GR71G* zP|R2W^1K=8E0vWOO|ZJ#eT@m0)UNjXGW{jhx?jxSus;EUk_GeM)FDwbm$;7DknRUm zq~_2+UTYgFgNEt9K(&~CQjJWfmZWMzW0LbS5|D)mJ+wqN3&Ez2|FIx`XHB8JDsgJ{ zfTo7WVr5+>Qvq!lby1qDjs`2Cb_QF}+|*pWe3|OA@tIPk6nSU76gHh$%kXe5_WR(J z{^gAbGz_)@788O(z)V!8yndTJHB(e!JlB0q*)F}e7=TD)eDXE|k{pCHt9L{FyDaIX zWH&YBd=cy6hLHSpO772dWw-B=029_@=bJCzkYt4pKoaC)QfgmbyBeCBpLy^p@A zMt>U>H&uA4`&p#*dL-|utAO6r4haA~M|1#P(y8)V`-sjKcLV23sbsKkZ>2p}RjN)U zOPGwt$6l@NlWW>C;Kk2=k%iuNj@4<8KKq#|&aGvYlah`RsRZ^~`PxfJ6z8TkySz_W zT+;Omu56G1y$I>aTpob_a>U%!}SegB-DA@(#_ zYI#ma`}yth4P92Zr;oJawc_R~jN5ucpmmAuisv?ty-6gz-r>4Ac#y%_)4gl0?_oeB z+@%(8kOB96{D#F;=`>RZJWLqy8r%%}8ukZcdOyPPx7@*wIqMkJd~eQW)1SB1fU62V zg&e}GL?hGScL2pD)}+1BK&>@xNcVP#S53AfJ`+*BaBnZmdR(D0Kyle{EXSo$Pinkb9;Y)VUv)2X-DhnGy`u)bS8nB0J@rTRL!QSUU3#- zLnmC)CT5(OhzP;CB<76?FmfhlB^JVzU$hUF33=>2iZdK|(7sd~g215x@AK5O#cf=Aqn77QEy?OoOqrkCbKf-6v`F5v z=XvgTiH1xf9`H!GBN&rJZ~4sP_%1HR>31c~5`XIDns$4`xRFNII*?N3@Y!Nxo(zHD z%jOckSua?7QxD0a6wyzyA7wU|Y%{8CW&M`thrGJTr}Lzi*X?T2M}f!OG<#LUHL~0u zXbxKMAKSdFv7ZXyr6V^?RvWLJl?Im-FLaEJ3lKQ$>1y|RTb7e`I)_T%lcXg{}; z)Hm1W=j&fCsJ>6R;pSVB|1|SyCSClEmd~|vg+}s)%&IGQRBa^XeRSmaWDD0-i^Sxg z<;F?K+dX<|US<2})*SVFhF6sgXzcVs`U$<0pBu*djBY+A#z7cC<#(9Teq|5w#&wij z*jkM$otMyO_^6;~kQEU}p37Q_9e;En^Dg-Ior1iNcSx>D#Gv=G568u)jXR6Vx~>Fr zDRD&xFL{%Rx1;)yX>xSj!(s{=S190v&&sk#i_2K5gd{`HK=-^hV4eMCWN)pqUehq^ ztT(zjOnDp69+@L*Ro;N-{MKJzWazFt#Tzta_ta?EWX($n;%7f86SC+5u2x2Y*HU~HyR0oX%t-Qex~vl_ z20r9lqDO@^$`yz_O32b{Zk%}q4*2Ct~rT-Wb5FshHLL}O{IfPvFwPfT0v zfBo35k1aBdgG?ZBYZc4EOurg)6Hz5Rr=P0B0~j94JK(H=@Cch;nQ^pMSKsG}O!}mh zQpR#c{%G}50NX%zSeA8F^N`_6E8+pSpvvJFdPBGqIHgpN)40aAi4IGn8)J+9^jghy z2)OD558|advDTmJX?-#n^jTW*c~hMncYj5Cv9{zx9cQ954-s2)P5IVH9zuU&4%*T3 z*ooi%;90lt8vBdo`GZ7<#dPCV*SDl`PEGzNkaVJ$a~xeU2GM0k?}v*hwp1J*=|Q-k zQv?Tcd~Xb(^@zOOp|+iREfI@%Kd8c8+(U_kRDq#+R;DXDOMW}Lg&lMzzcw~@hy$K+ zY!XB1i0V8GQlnYDjS@{M+|MZ!@ApW4{V9rs%Ao}IHOzf1{0%nYI%CH8;>?FEAg}w6 zrKgMN?u*x+MU^TV2)HdpFHtTH6`Bb^3QnE8BU~T8^6**QPD8USH#Qoqy{=KDso)Z! zGRgAz$^FkSXd_0abBk+oyy8u`DOn>|Gcc!V+J(eF-e^tIoW4I}#`OFF9bp{AC@+(w zbJv+1J3}sn+H}k)XOuvY*ID(nKKaE%lAz&=n>V;KC$_mvcDR%$yjaBq)_~O%Uep^8 z%8*#j5>H2WjtK6f^D`um8Fg$q%oumBY+UuG(^4s|@JBm451q8E zV3AD+2u>Y?4xh0a`RF7jw5FWh5~v&K|8VSj>}BVpO&6NiK7Wn^ghA3^@B1qT{Nr@0 zuP7vl1B#V@$02`3I-%5m{Zt&Df1Zj1#X&ECLFiUtD9HHjVLO+gBP%x)MrP&UfugTK z4o)cU2>S6{9KK&+$IF6$Mjd%Tya4TQ2qYJX>wkqo{y4AdJIpO1CwWoF3m_Bv92w}{ z4r|f%g86#cJts=&^GF4M6NbJx(q@0|Nk*o0^9+1Z*c~Z{Z*)2vBozbhHKA zT_^wuP;xQ{J3%2~203#m!5ZSh2v7xET0`+o4+b%F2U9R3G$dP6>+&fTx}ei0#|`U9>0E*h)s zUnRJ}#($IGUxW!j(d1vk1fZtyElPm<;u%Q)An5<%u}lBAP&&ttSo=#j9*X&2$^k6~ z+6JJ@u!ZlmOYmCB1!8M$4|e`Z%|AlgzixAP4m0ts%BxhO=`Rbr>*= zI}8NI8pZ*J3Pu{n1;!r6?A!nLFwQXiFjUYs#Q@twTh|8TGWS>QN$OpOH>d)%b#$RD zxp;t7_Aa)z1^_jHjDxzvPkDX>W_+y=FE8}u6tKM|#EOcYtYcom&O zh;eTe^e<4G(ss?;Yc*@QOky?Oa?f!3d}GhR#;H;>bV#<6&7SMA;6VcEE&H_GuGmHo zo5yo$U8mfkR*DMf!%IWE+i$S}5;j$GO}QiE!Zq8qT(?S|xc1n6yq(r1Sdw3=qGT7_ zU^wf0-HzzAaR`Gj=-BF*onen}Vcn_P2l8m>fwjNn_0?6Dy&{Pf!Ev_M$3rRdE8|vZ zvWcFF>~hr=_t>@`>xpr2(pZC1(d0f%vt3G#u z4*ny5(rb{OZNNT`K^WNsQqD+qn5Nqqpd+ZsBF0#ovC`T_x zW)0MhAiA2$thx(UL1J&&Wwg5DkDs9t^xUlglj|-lNyudnHkhepgQH9uc;d+8e7V>2 zB3Shjt;sbtZ-S$+4c4GV=p-l9XshjOb?Ll+fbc;TmC>*?zu6tgq`6=vSnfUUQ-0HM z!Aj`pu=;pP3YGO;ysk%bPIS?OL_Tq~?b6qvIM0NmSJmX{$JJOQDmf40ZJL|>cDbjk((xBBT{)<10Q+)22=|Q9Zf4Krj14k*go96W52CWJ;v8W~uU1cCKE1V+kt{MW3Jp!qc`W9q+t}E+99}4T#9P%d>n|(^%5S3c-wx$LV1Ys|3EPRmNucZg( zPcgcqrc-Q39Fgo*Sv>#rMiptra%i9+Lq#OVmwU7f;o`#b(Lpo3xRAbI6wlec!G|xm z;-{J0wL;6#jpFfzYp3@9xiF@nSCwIFdq%h+elxKrXxDV9^UZ@SA_+jKA^QJ-F!q!P zL8*#1BwgY%FQ8#f)r(*EPHW#~gLO-NbkfAJ+yc&juK#3}h@6B+iyp=U2(H0i?zabpy z0H&s)nXUo;cCqgSDj{T`3KMuU9jb2?PN}u!|0_a<3mnCdbXFl6vLR{=Au7lrN=w1e z;~#Dn1k2qEmaz(!k`0z%pp`>`|Lo68g@FuL>CZrgf_%-%pO^{(8TJNzFgCWh=*11~ zK=$KSHci00w^7A|!^?+9hb#wc3lqmXsTPz^zMz5nT95}%V)^?9#8EhEQFvTY1olxx zFs-@G6|3mz`ko9ys^>ea1CJYDVfhVu6GmsfU0Uf}+1|IQB3JrUI=j8|cA>A&SKp`Q zlYxk~(LmyW17_ZaKoN>XU3-aePz*MHRpj_%hTtdPAvCa^^NRn9cCmRD5bCOZ;ohf zFHG+{H3~%Br7@)F%=z41Oj(yWdp7HNjuSmR|9NqCK4)Thc%x-@-od`xhB9$p*idM^ z>{I06kY!5yaP`=Sy!-3q0_mwNer$CP(-kMC{EbU9dtZwEy8F&%8M}9m&%HgIR9Rl& zNV(5hPtSCwEb;ac&Y$K)?UmoP{0n&f?;(|W4f+u= z3}`8-vLWHZVd-TEJGRKl1l&e~uj}p!1T`2(uoBOrb#c~pzqUkaS)CYcY@Rrdb-p*C z_{L`#-g)zR(Sh=?o|A!F;cBVNL`iAmsEfl&L!HaSDsMc$YF?B^iJ8W#_AtL@&7Ze5 z{F)_E8pUSAE82hDmYEH=yk1$}JKA&K%x|w(`m*W4f3wA{#-qw0jbh}uedWu_@{t6e z+WDxj^S#X?%9lFFgQxF{XIqbFl^RbES9`iYyt?a^#0Cv{axhRZrY!RlsA5gmf%Fb# zoMJc^OMZFPV)%Sauh>&h!=Y?tLVeG^*wam;`M79Of?Ocpe58WW1tL$Lp(;}_1Y&ZD zlPAy5I1~Lcfwg!-Afoo%>EQxhka;ha0eepZ`e(YJ$8|hc5;_hlVoWzHB0t$EwC=2WLU`yl8{J1_bk;&Q$lQ%Jvau14QJ%M96RV6zRmvmP=akyOQkcMF z712C_Ed^2&PE8G&Q4;sau_uwE$Rk$ea0im!V%_Q?6%XK=9aSdmHMXB+YoHaHWOpPt zL5_Pw@$?yeA1|URd&E7=bX^v9Y~mi(aB)urW+ye}_Er;r0-YD4!w5J9)84YyKtU$h z1)NVRFvJudLGLS~VZu1z-ORJOk`P|kbkYNPPyoO>QZSq|02a|X8eRqGRa?-GH3^cc zqw!Noy3Fj(HbMTnGcMQcKdjpH87*6GP9p?dYQa5rt zZNCTBePeekgoW_&djZeH?ZwDTq#`k1W1OcpH&4Ul*UoJ2Tf1kxbbO4h-;|0$Ig+yZ zAZ2%r~y^}3kT}U6WX(%V0;cLJB(C&K&}(K6KVCPdN$LsrsgcDKAbf9NBQC+7YF!Z{6iJ{8-{=8#a)# zy1uuvV&0q@I@|YU)T_IF*{M0%*NdVgVbG@0%coBFY`d1m%U#PaEkoKfD=;LMN5(;I z62ToX@?~N@SVQt?K3Q^Yv+fgzRldcwzrGhOuKkO5pygC*(ThT+IlnkH4PK3qUw_4` zY4B;pH+eE@0Ggj%y5aut#t7H>dC;#Q9IB!1@2|6gspF9L%_|Pni?k7d?eb z*JCu92|D1)MWwW6_})~9tE=Ky;vR4E(dXHQzgtkGs|GahAHGf|$*7nuidKE#iN7he zsQY3&hMMirCI+-slg&N*phj#=|8@OjxXZZLT@-JbZNxP)aA|9eu7#s@EIX2;!Yz&| zf9oJ;zyx-4UtVl}4SU>d?c_g;=CIZN6zOyIy68M(1Nfd)FTuAR{TS=Dpc1w{(maCEWx zF;)@=38bVTLRxyU+y2?_nDOC0!zYBi{^)GNf@r}=npvJ1@}Z;}eS>J?S%7g(yL6HX z)l&>zbuerItXiAB9+(*43fkvi*wBO+zq#*xl2zl3sHDPTGJugcgLU)BxC_S4n4vc* z4n?pJ#exGpFeZSxO?zJvm}J?XH24wIymLGNF18CBb)g@d0k^M%4(Jx@@6Jsu-X=&a zZh{f243rU>Q*C00Kk8wY$OIW^S27}6*|t+;2}OP()LMKO0V|=+Y>$MlODxHP0QV$7 zT1p0H%{cwO7?W^pcf3zOQ`^Tk>57Mo`85f*vMI4|8V|729tuZewa*Ob&Gy3(XF^|AFX6_)NdV2*lDi) zx!;xt?)2*M>K>Z5f-!5r9=xlfvEH>0M8=c{9;uza@8+JJ@%FKB#e|wy$40n6Qc+_6 zEGI3}i_9PdM?vCf-Y?tdua*zU$+W;9iU@qHqRfH1f{SoEC*-qGnW8i~f|mC5d6yin zVl-Fs^P7*FZ$1LJ@*iwGn6Rckfnc;d+DlSAF;>N*7x z-ohu_vh!r8J)4&Cb&n{n_$Tq9O_oRcM~Gci2qM8f+LEDy%x`s(J6^I}zjr3ALBm&zE0-?(Fl=Hu zy`)Gu@m*?+hZ0|M^j!MWxgi0zM;-WD3hz8VJko6&j@=Ju9vN}$^z5vg<91x{MH+f3 z+exR>SBSo(E;o#!rQjl3rfY*~zc++KIzRembuCMfnBLEJqK<|~DB#a%h zN~R?Ss0ijGIvRtvvm^kXh=sI`>ppWE#sg_!+yh+n`M@+61}(UH3F!H7+c6d}ZVWsN zk-D-xfmt7u88==!24)E+U0=yc?%fMOsDe`rS;mkndX2@U0uBrc0S6j0y|T=qb-BrF z^UjoE+)BF~?ajNF+~^EiscR%JF(S9n=R;%3SH|C>4k%j$r$e7`fj*#2!Ta9BP+CAR zCxisav#YHDjnInvo$MWW)a&(`k%%Coj=ru&s++25QU~I|k{j@Y*W;(Up5VRS&%2}`NnibUv6p>0kD?`=%clMl}uuozJDh0jK)m1Ku(AYl3WR)E89Tj$~{5m)+* zs78sGA`2n@u^&=aPo3^I36dpZy?Q@?I+4*mU)SEZZQ*yCUM6Q57TqF(t>l)mf!XMn zB(hoNdQ6jEGS>3JNXY)nYSF%n$U&w0f>A=c>Uct8-XbHn(zb_ua{kbl@EQ;KjQj{u zW}5Xx7|SZyL%=XJ0TD07R2)n`A}?#}GHid+q7|kiZ7a&5D4g&ce=N=^I1K2m65Pa6 z(79QG_5`nblQ0R>-mQAed^fFwh{5M2GCu5zx|4{8r-SC#-MJJ8?WTr7HBFectY+;C z-Ca9zwP}^swqqw_<*nb|?g3`7QAoUWt%b0Ptq8c~0q_@!S|X%8VQqz(SIM3In^*XO zNqqAPyuj~X0R-au+oK8pT;csUQ;BMA1qT`)^i$?*o*TNfQa&&b5Go%C*~Zq2;TdB| zVcE~ZBdRt!HjD0T9v5u$21QzCgB}ht%y>oP%E>{*d-@x(!_{2HnrSGv=wwK@!QH~M z%uzJPq^atS{3zU%Y522rL>*g6uehb?WfB<& zj*XaBW{w~zB7nHg7{*jqn>N|z1yeE#To=q8tT)t(nfX()#JlidxzGS7swG;6Q3QI1 zVm^cbPEkGy9W)@xOOSthmcCYMR_Zlvl9#1m2qx1S zmEl_!;&SltVvHvKfyyrxt1&a5B0pk}qwx=abFWi}zQ@b|{OqsAdv!@B$~Ml~Ig;5@tsCfUQ;Z%dTR%MLb)h>#&KvX1TU z-VX+p#=Jfn?VCBe`)u;0^~`nelkeTrsg4B^Z(hgh#U7H>H~oC23VM8V(Wzq_^!urt zbKc{VB{$1G5NoT=I$J`0CUf4L)XO@j&nI!jaGV5loGhJ;KkO3xbW(M4$K`H|(R!-i zA`xP}yS|7mp@`41Tg!7l-IIoTU17VHbs{6T)l<)%t*VeS8@FRinbZ1)PaB#t8;N}r zHdSSQzLOs@&KlkW+?q9J1kOYI{c;7D4cpsJ>FhC$XdniZwQQPNM*Opz`yD1l&mAY~ zAfM*2jQG937?+_On-L!tPvVsJgJkwJ$atJm*`Gk&7kdI|R?25TEN>K{6`QioO-WOf zlc52&fzXYp7PPw)BkYl_BvDBIa$VU2O_jN`AtcI_r@HwI zo}4FQA}X7mab=wD&YRFD;ZLMFwK#dQ^Rn}B$eH*#vum-pYDbn<+ z2J%F5)E9_IjyZTaTiEYZft&BBJ+(;zW7uDBSV$tR($r&KEl&B|YDuQAxc+P~wr`k| zKFzjr{N!GSk(Rin;~{!f^<8PN2ji$sQhH`~-6_v}OA7h+)f4xKEDx$bY_@Gae%!vi zGN9l`eWWWg(G8Pn$n}sy{XG z^fc0uCQ?3+2AT{pntj(3G_+Ptnv?_6fmX;h%O}(K{l=N0@cyVloLc0Eb-6hK zJw#SEqFAM!iDyPHkm}loz*|Cvg~`|Tl4@CObK||p(-+%b3G#kPc7J?-G1)!&KGsfA zAVg6o*d(7jBfj5so{z%6 zg}8qPwf>FEON~*w)d9rrYW} z!yI$w+giFs)b@{tvXgJwB$PDJD0voB=i$8MatN{M^D}rc6Lyi%;T zi`S#aXmQJh;)tqN_>Igq?f!cAAz|k$&W;RMp@I;CM;+2Jr$Uf1>|DMZaOG>|a|$ z*~Aj;47g=&?ySdo36D~7UM^?-%=3c&mFG7^mGc)=_8VCF6DKb2i}f{Cstb8lsV);! zU2>(m+~G`h32;L<2!BoVwOG)%EEl8fUuyINLj7Cme^%r2Ky+2AuL$kW)%daI_Z@%N zR=EBByPAU+`n`P#DJy^>Cgvs(lOGFuf+FsYCT4fQ5GqqB;BPNPz1i48O=WE^M6Jc8 z090_409#qhdOCsCJQdZ=JnxwCnNy1hqYAq7yW2V1LAg=6+u7PX^ScXCn_R>R@I&t} z$N*}p%OsFHLev~=AXXkAh*}txii%3m$=rfpRZ{v}KInf!)K(CPBR>G(=H|xc#=+*` zWC;NA@$mtG>;QIlR%i-VXAgUbi94&kGtE~f-}!tGh_H6Br@G*4V(Q=m5u&EPDCnQp zR{;$-&&k4D2KgvLWy z+uDMisCd|bR1DDF^X3k2&WwT=EPkZ^R<I}{8t}j10sNWAPbq)n z@!f3y1(#nX`DWsmY5&`eVQ%(MTR6Hn*i}BW4TvmHOS7Y^^Uk6ThvAy`>Pf zJF7X^!oFQai}+>a&ZPb&G;ufQ(3xLn}fd^sjc;|e7{nE zE$&j>-z5`-N^ADj*nZ=1VdHAxyT4L@$SW)bJ)*ph^hf`4arh-_*?qAe&@yTC( zsyqL;rv6t3aFO$$G(RcglCI|9;$#NC^fcCBb74vT3!empp2h;=1aW|PFa5AP|8J@O zZLPoB4D{Ow`i%zo=PT_GtNq#u|I5FB)b78`_-A%kh5W3I|9F3;uK%c_pA%fE>t}8J z$NMXF{YMr3oZw1bKWpPZ-e0NfKdR{G1piK5s6Qsf&>$EgYB%VV_isxUKQQ&nsS9*u ze=+G`_-SAQ1aWX&%yH;}Kzc@imT{>E!_NHO*9^Un`ZnJXzuO= zw!lDzhLv-3LjU~pqT=S_f`%Ghe01>waX<&LRF}6@_W#iMxS>mP7q1^QUJwY{2*1%d zxPH$I9U^l4o{k+FqYhnu`6Vwq4+k%FMdvpf_r->RUuYaa4yY8r)42YS8QS=KzsmwW z>5uCVe$YK9(3PTJ%i!j^*j4cx4JzPoG)^Fh_xE(1Kdh<>Q8$3v^NMx4hhcmcb4D z!~URiGT`rZ6;123456789>;7=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<95?0137?567:=1;<=6;;123=1=78?:97=?;;13341=7999?7=<>35936653399;>?5?4593053339>9:95?5061?5>33929M95?89:7?5>?K=1;O=6>;0685567<2;;N=?n;009KPRW]]0bb~z}_`fgv976294?7<:960685020?699=1:97GAPTV9EABUJ5;?6=0>8:3;>LHW]]0bb~z}_ekm841=8780=O:41G365>433;:;<95=01:7?745?=194=>=;3D26>552@D[YY4KI@>05?699;18>7GAPTV9@LD;;80;2<=4338LQQVR\3NDM1=>:1<27>552F__\XZ5DN@?74<76=185:?;;2@4B4=3:2>;86:?016801C3<2>>98:4472154=32@D[YY4KIQC?7?69981?6D@_UU8GMUD;;3:5==5;:HLSQQ0:69MKVR\3]NN1=50?31?10>586:2>1CXZ_UU8GKUD;;3:586;JFD3821=18<:?7;>N039561=10:=97;M;;63071=0?;H?7:J?9594BDD33>LMO<572::30>>789>04=ON4::3BC2<01L3=857:HLSQQ<elgThd`37;2=52=?2F__\XZ5xlgn[dbcz5=1<3?8;98LQQVR\3rfi`Qkotv?3?69923?74::559:=3?53H:97L?=;@01?D533H9J<95N8327?D>AN=1JMLM;;@CAE1=FIJ:?7LOLA39BG1=FKHK?7LMNF99B@ATF49427LJKR@>24;?>89B@ATF488556OKDSC?568e3HNO^L2>4;2==>GCL[K7=907;@FGVD:6611JHI\N<3<;?DBCZH68255NDEPB818?3HNO^L2:>99B@ATF4?437LJKR@>4:==FLMXJ0507;@FGVD:>611JHI\M<1<:?DBCZK6:<374AEFQF976601JHI\M<00==>GCL[H7=>0m;@FGVG:6<3:556OKDS@?518?3HNO^O2>>99B@ATE4;437LJKRC>0:==FLMXI0907;@FGVG:2611JHI\M<7<;?DBCZK6<255NDEPA8=8?3HNO^O26>59A01D33K?>9?5M859A0OH>N4:AEGD40OAEN4:AOOG5;E68@5>7<2N>4=<4D968@=@7<2N3JK<4DH48@LG;87=0HDO311<4?AOF48;5;6JFA=31:2=CAH6:?394DHC?51803MCJ0<;17:FJE9716>1OEL2>7?58@LG;914<7IGN<0;=2>BNI5;5;6JFA=03:2=CAH69=394DHC?67803MCJ0?=17:FJE9436>1OEL2=5?58@LG;:?4<7IGN<35=3>BNI5832:5KI@>1=;0394DHC?758>3MCJ0>?50?58@LG;;84=7IGN<2<5?AOF4=4=7IGN<4<5?AOF4?4=7IGN<6<5?AOF414=7IGN<8<5?AOE494<7IGM<02=3>BNJ5;:2:5KIC>26;108;EKA8429?2NBN1?:>69GMG:6>7=0HDL316<4?AOE4825;6JFB=3::3=CAK6:2:5KIC>14;1<08;EKA8749?2NBN1<<>69GMG:5<7=0HDL324<4?AOE4;<5;6JFB=04:2=CAK694394DH@?6<813MCI0?08;EKA866912NBN1=>:1<4?AOE4:;5:6JFB=1=2>BNJ5>5:6JFB=7=2>BNJ5<5:6JFB=5=2>BNJ525:6JFB=;=3>BNXH6;2:5KIQC?5;12:2=CAYH7>374DHRA86<76>1OE]L33?48@JG;87=0HBO311<4?AIF48;5;6J@A=31:2=CGH6:?394DNC?51803MEJ0<;17:FLE9716>1OCL2>7?58@JG;914<7IAN<0;=2>BHI5;5;6J@A=03:2=CGH69=394DNC?67803MEJ0?=17:FLE9436>1OCL2=5?58@JG;:?4<7IAN<35=3>BHI5832:5KO@>1=;0394DNC?758>3MEJ0>?50?58@JG;;84=7IAN<2<5?AIF4=4=7IAN<4<5?AIF4?4=7IAN<6<5?AIF414=7IAN<8<4?AIFW[OL:6J@B=2=3>BHJ5;;2:5KOC>25;169GKG:6=7=0HBL317<4?AIE48=5;6J@B=3;:2=CGK6:5384DN@?5;1=08;EMA8779?2NDN1<=>69GKG:5;7=0HBL325<4?AIE4;?5;6J@B=05:2=CGK69;394DN@?6=803MEI0?716:FLF949?2NDN1=?>89GKG:493:5;6J@B=12:3=CGK682;5KOC>7:3=CGK6>2;5KOC>5:3=CGK6<2;5KOC>;:3=CGK622:5KOC]QAB189GKUG;;3:5;6J@P@>0:2=CGYH7<394DNRA84803ME[N1<19:FLTG:4294<7IA_B=1=7>BWG<1O\_O?5:FSVD723MZYM?;4DQPB74=B<2O9ML<4E568A103:2O>86K84608AD2@4=9>0J>K=4:D67C4>0J:L<4:D:EC2@CKL90JIK<;GFS7>@CZ;1MI95IEGA7?C@70=1MJ8:;;GD4B1=ANH2?7KHNE59EBG@33OLHM95IFBG7?C@C==1MJI6;;GDFE1=ANLL?7KHI459EBC>33OLMI<5H3:EM@4=N:2C;>6G>2:K16>O402CEEY^P01:8MKOSXV::46GAIUR\47><8:KMMQVX8=20ECG[P^26<>OIA]ZT<;64IOKWTZ6012CEEY][AUG4?LHN\V:;;6GAIU]352=NF@^T;7:KMMQY7=>1BBDZP0758MKOSW9=<7D@FT^2;3>OIA]U;5:5FNHV\4D11BBDZP1758MKOSW8=<7D@FT^3;3>OIA]U:5:5FNHV\5D1D69JJLRX9L=0ECG[_0D4?LHN\V8;;6GAIU]152=NF@^T>?94IOKW[7503@DBXR<;7:KMMQY5=>1BBDZP2758MKOSW;=<7D@FT^0;3>OIA]U95:5FNHV\6D11BBDZP3758MKOSW:=<7D@FT^1;3>OIA]U85:5FNHV\7D1L8;HLJPZ5D?2CEEYQRJ;;MWW73=K]]9TH;5CUU1\H1=K]]>=7A[[4^F5?ISS7@[WCX78IP^A=<1FYUH9109Nip~XzlmThd`P2^d656=Je|rT~hiPdhl\6Z`2W9;87@czx^pfcZbnfV8Tj8Q>129Nip~XzlmThd`P2^d6[7743Dg~tR|jg^fjjZ4Xn5Bmtz\v`aXl`dT>Rh:_530?HkrpVxnkRjfn^0\b0Y29:1FaxvPrde\`lhX:Vl>S;k4Mlw{[wc`WmceS>h4Mlw{[wc`WmceS>?i;Lov|ZtboVnbbR==f:Onq}YumnUoecQ<3g9Nip~XzlmThd`P35d8IhsW{olSiga_27e?HkrpVxnkRjfn^15b>Kj}qUyijQkio]03`=Je|rT~hiPdhl\0c=Je|rT~hiPdhl\04`<>6@?3:L357=I9:1E==:4N0221>H68:;>7C??3318J4733G;:<95A1037?K76:<1E=<;74:L25352416?K75==?0B<<:549M573?=2D:>;>:;O31273H6:?<>7C?=6678J4410<1E=?865:L262623G;9;<;4N00460=I9;=896@>2666?K75?5>:;O31<73H6:12>7C?=9178J44>:<1E=?7;5:L26<023G;955=4N016?K7489?0B<=?249M5663=2D:?=8:;O304=23026?K749;?0B<==549M5641=2D:??6:;O3075385A12171>H6;:<>7C?<3978J4538<1E=>:=5:L271223G;88;;4N017<0=I9:?;96@>3406?K74==?0B<=:649M563?=2D:?;>:;O30213H6;>>>7C?<7478J450?<1E=>965:L27=623G;84?;4N01;00=I9:2>96@>39;6?K7419?0B<=6149M56?5=2D:?4=:;O30=13H6;0=>7C?<9978J45>1<1E=9>?5:L205723G;?4176?K738??0B<:?749M516?=2D:8=7;;O3750=I9=;;96@>4046?K739>?0B<:>849M517>=2D:8?>:;O376439>85A15001>H6<;>>7C?;2478J425><1E=9<85:L207>23G;?>4;4N06040=I9=9:96@>4206?K73;:?0B<:<449M5152=2D:8>8:;O377238485A151:1>H6<=:>7C?;4078J423:<1E=9:<5:L201223G;?88;4N06720=I9=><96@>45:6?K73<0?0B<::049M5133=2D:88;:;O37133>;85A157;1>H6<<3>7C?;6178J4219<1E=98=5:L203523G;?:9;4N06510=I9=<=96@>4756?K73>1?0B<:9949M5117;2D:995A1437?K719=1E=;<;;O3476=I9190B<7=;O00?K47;2D9=95A2027?K469:1E>9:4N3647>H5=:1E>5=4N3;1?K543G9:86@<1168J676;2D8>>5A3218J6243G9>?6@<659M73543G9:?6@;229M065H28=1E9=?<;O720>H29890B8=<;O7;7>H21=1E94?;;O7:71=I=0>?7C8?659M25143G<:?6@9259M2=233G<3995A6957?K0?0;1E;>5A7018J=743G29?6@6129M=71;P38V==UID;=T19:Pfwpjs48427_k|umv?6;?89Qavsk|5>556\jstnw808>3[oxyaz36?;8V`urd}6<245]erwop9>992Y37^OYEECWE3=TG\XHI>5\PN58WWPFDVK<7^\YAM]A0>UTZH>0_^\M4:VZT@e<]ZOYS[G\ICNF7>PDK01]EHYPTXRF0>QDDB80[H84WDC?4;0<_LK7=384WDC?6;><_LK7?7>16:UFE959>2]NN1>16:UFF979>2]NN1<18:UFF95=87<0[HL33?`8SWOSMVLB^^Zl;VPJP@YJGMOTMn5XRHVF[HICMVHo7Z\FTD]TMAROWHn0[_G[E^UJ@QNXJ8n0TDBFNY/[@G&7&8*XXXL/0/3#EVENA<1SC_MV6:ZPPIOE?2RXXRIAD69[WQYQKJ<0TilPIe33?]bjWDkacXjrrklj463:4ggk}Ve{=1=11`9bhpYhx86?2o5nlt]lt4:368k0ma{Poq3?1;dc9bhpYhx;6;2^d6e>gk}Ve{>1=1b:coqZiw:595=o5nlt]lt7:46;n0ma{Poq0?7;Ya=h1j`xQ`p3>7:g=fd|Ud|?2;>0`8eisXgy8783gk}Ve{>1;1_g7b?djrWfz90;0m;`nv[jv54?4:n6ocu^ms6909:m1j`xQ`p3>5:Z`2i2kgyRa2=5=f>gk}Ve{>1911c9bhpYhx;6<2?j4amw\ku4;?7Um9?5le69`mjYtme;87ng`_rgo[fkwWl{;<=>>3:aoof=delgTmij}<8<`?fkbeVndyy2?>b9`i`kXlf0<0l;bofiZbh}}692n5lmdo\`jss4:4h7ncjm^flqq:36j1hahcPdnww808d3jgnaRj`uu>5:f=delgThb{{<6<4?fkbeV}nn6mbel]taZUP9:1h|xo4cqw\efrn~l=0okh_vg;?ftboV}n=i5fnrv\IwgjWdofi6gasu]NvdkXelg:i6gasu]NvdkXelg9i6gasu]NvdkXelg8i6gasu]NvdkXelg?i6gasu]NvdkXelg>i6gasu]NvdkXelg=i6gasu]NvdkXelg9b9jjvrXie$B?>k;hlppZgk}&D9=oi{}Uj`x!ndeqvfZoi{}%Fmij|uc]pqhYj}q:;<=Qly=2=6`=nfz~Tma{ aefpqgYnfz~$Aljkst`\wpkXe|r;<=>Pcx>2:7c?_b{?6;4b3`dxxRocu.cg`vseW`dxx"CndeqvfZureVg~t=>?0^az8685m2ceyQnlt-b`aurjVcey!BaefpqgYt}dUfyu>?01]`}929:l1bb~zPamw,eabt}kUbb~z M`fgwpdX{|gTaxv?012\g|:26;o0ec}{_`nv+dbc{|hTec}{/Lcg`vseWzfS`{w0123[f;>78n7d`|t^coq*gclziSd`|t.Ob`aurjVy~aRczx1234Ze~4>49i6gasu]bhp)flmy~nRgasu-Neabt}kUxy`Qbuy2345Ydq525>k5fnrv\eis(imnxyoQfnrv,Idbc{|hTxcPmtz3456Xd|~7<3Pltv?0;4a3`dxxRocu.cg`vseW`dxx"CndeqvfZureVg~t=>?0^nvp939:o1bb~zPamw,eabt}kUbb~z M`fgwpdX{|gTaxv?012\hpr;>78m7d`|t^coq*gclziSd`|t.Ob`aurjVy~aRczx1234Zjr|5=5>k5fnrv\eis(imnxyoQfnrv,Idbc{|hTxcPmtz3456Xd|~743Pxnp?0;4a3`dxxRocu.cg`vseW`dxx"CndeqvfZureVg~t=>?0^zlv939:o1bb~zPamw,eabt}kUbb~z M`fgwpdX{|gTaxv?012\|jt;>78m7d`|t^coq*gclziSd`|t.Ob`aurjVy~aRczx1234Z~hz5=5>k5fnrv\eis(imnxyoQfnrv,Idbc{|hTxcPmtz3456Xpfx74320:8mkusWhf~#ljkst`\mkus'G;8=:5fnrv\eis(imnxyoQfnrv,J0703`dxxRocu.cg`vseW`dxx"@9169jjvrXie$mij|uc]jjvr(F>;<7d`|t^coq*gclziSd`|t.L;52=nfz~Tma{ aefpqgYnfz~$B4<<;hlppZgk}&koh~{m_hlpp*ureVg~t=>?1=2=61=nfz~Tma{ aefpqgYnfz~$xcPmtz3457;87;9<6gasu]bhp)flmy~nRgasu-pqhYj}q:;<><>;hlppZgk}&koh~{m_hlpp*ureVg~t=>?3301?lht|Vkgy"okdrwa[lht|&y~aRczx1237776;2ceyQnlt-qavYumn6;2<=4ioqw[djr'{oxSkh<0<27>oi{}Uj`x!}er]qab:56890ec}{_`nv+wctW{ol0>0>3:kmwqYfd|%yi~Q}ef>7:45018mkusWhf~#k|_sgd8286:2ceyQnlt-qavYumnU;=?5fnrv\eis(zlyT~hiP1008mkusWhf~#k|_sgd[7753`dxxRocu.pfwZtboV9:>6gasu]bhp)umzUyijQ;139jjvrXie$~h}Prde\1442:kmwqYfd|%yi~{ct=2=50=nfz~Tma{ rdqvhq:76883=95fnrv\eis(zly~`y2?>0422>oi{}Uj`x!}erwop9699?UM=;5fnrv\eis(zly~`y2?>04\C43:46gasu]bhp)umzgx1>145]PS5733`dxxRocu.pfwpjs494>=<64ioqw[djr'{oxyaz30?77[VQ79h1bb~zPamw,v`urd}6;28:PSV2\B4goi{}Uj`x!}erwop97998;?7d`|t^coq*tb{|f0<0>9068mkusWhf~#k|umv?5;529:1bb~zPamw,v`urd}6:29?<;hlppZgk}&xnxb{<0<651=nfz~Tma{ rdqvhq:66<;:86gasu]bhp)umzgx1?1733;?lht|Vkgy"|jstnw848Xehz:?<64ioqw[djr'{oxyaz31?]neu719>1bb~zPamw,v`urd}6:2Rcnp334?lht|Vkgy"|jstnw848Xehz8=:5fnrv\eis(zly~`y2>>^obt0703`dxxRocu.pfwpjs484Tal~7139jjvrXie$~h}zlu>1:420;20>oi{}Uj`x!}erwop949;<;87d`|t^coq*tb{|f0?0;129jjvrXie$~h}zlu>1:0733`dxxRocu.pfwpjs4;4>=<:4ioqw[djr'{oxyaz32?515==nfz~Tma{ rdqvhq:56Vgj|<=>8:kmwqYfd|%yi~{ct=0=[hgw9?;<7d`|t^coq*tb{|f0?0Pm`r152=nfz~Tma{ rdqvhq:56Vgj|>?8;hlppZgk}&xnxb{<3<\idv29>1bb~zPamw,v`urd}692Rcnp931?lht|Vkgy"|jstnw8686<2ceyQnlt-qavsk|595==>5fnrv\eis(zly~`y2<>530?lht|Vkgy"|jstnw86829=1bb~zPamw,v`urd}6828?>4:kmwqYfd|%yi~{ct=1=377?3`dxxRocu.pfwpjs4:4Tal~>30:8mkusWhf~#k|umv?7;Yjiy;==:5fnrv\eis(zly~`y2<>^obt7703`dxxRocu.pfwpjs4:4Tal~<169jjvrXie$~h}zlu>0:Zkfx<;<7d`|t^coq*tb{|f0>0Pm`r;57=nfz~Tma{ rdqvhq:368>0ec}{_`nv+wct}e~783?>159jjvrXie$~h}zlu>7:4?6<2ceyQnlt-qavsk|5>5?8?<;hlppZgk}&xnxb{<5<756=nfz~Tma{ rdqvhq:36<;?7d`|t^coq*tb{|f090:1068mkusWhf~#k|umv?0;15911bb~zPamw,v`urd}6?2Rcnp012<>oi{}Uj`x!}erwop929Wdk{=;?8;hlppZgk}&xnxb{<5<\idv59>1bb~zPamw,v`urd}6?2Rcnp234?lht|Vkgy"|jstnw818Xehz>=:5fnrv\eis(zly~`y2;>^obt=753`dxxRocu.pfwpjs4<4:86gasu]bhp)umzgx1;11037?lht|Vkgy"|jstnw808618>0ec}{_`nv+wct}e~793=:129jjvrXie$~h}zlu>6:1743`dxxRocu.pfwpjs4<4>=95fnrv\eis(zly~`y2:>4320>oi{}Uj`x!}erwop939?;;37d`|t^coq*tb{|f080Pm`r274>6:Zkfx;;<7d`|t^coq*tb{|f080Pm`r052=nfz~Tma{ rdqvhq:26Vgj|8?8;hlppZgk}&xnxb{<4<\idv?9;1bb~zPamw,v`urd}6=2<:4ioqw[djr'{oxyaz36?3251=nfz~Tma{ rdqvhq:1683:86gasu]bhp)umzgx1813430?lht|Vkgy"|jstnw83839:1bb~zPamw,v`urd}6=28?;;hlppZgk}&xnxb{<7<65427=9=55fnrv\eis(zly~`y29>^obt45602ceyQnlt-qavsk|5<5S`o1734?lht|Vkgy"|jstnw838Xehz9=:5fnrv\eis(zly~`y29>^obt6703`dxxRocu.pfwpjs4?4Tal~:169jjvrXie$~h}zlu>5:Zkfx1;97d`|t^coq*tb{|f0:0>5:kmwqYfd|%yi~{ct=5=5556<2ceyQnlt-qavsk|5=5=??;;hlppZgk}&xnxb{<6<23425fnrv\eis(zly~`y28>537?lht|Vkgy"|jstnw8283:8>0ec}{_`nv+wct}e~7;3::159jjvrXie$~h}zlu>4:306<2ceyQnlt-qavsk|5=54??7;hlppZgk}&xnxb{<6<\idv6<820ec}{_`nv+wct}e~7;3Qbaq3652=nfz~Tma{ rdqvhq:06Vgj|??7;hlppZgk}&xnxb{<6<\idv58820ec}{_`nv+wct}e~7;3Qbaq0052=nfz~Tma{ rdqvhq:06Vgj|;?8;hlppZgk}&xnxb{<6<\idv>9>1bb~zPamw,wqgsW{ol"no}rx35?lht|Vkgy"}{au]qab(}m{e:j6gasu]bhp)t|h~T~hiPc`pq}Zkrp9:;>05]PS54f3`dxxRocu.qweqYumnUhm|v_lw{456799>T_Z>PSV212>oi{}Uj`x!|t`v\v`aXkhxyuRczx1234463WZ]:>?5fnrv\eis({}kSkh_bcqv|Yj}q:;<=?>6308mkusWhf~#~znt^pfcZefz{sTaxv?012164453`dxxRocu.qweqYumnUhm|v_lw{4567::;9>6gasu]bhp)t|h~T~hiPc`pq}Zkrp9:;209jjvrXie$yo{_sgd[fguzpUfyu>?016664=nfz~Tma{ sucw[wc`Wjky~tQbuy23452>:81bb~zPamw,wqgsW{olSno}rx]nq}6789?=>85fnrv\eis({}kSkh_bcqv|Yj}q:;<=;9_RU360=nfz~Tma{ sucw[wc`Wjky~tQbuy234531WZ]:>45fnrv\eis({}kSkh_bcqv|Yj}q:;<=;9_RU2[VQ7:81bb~zPamw,wqgsW{olSno}rx]nq}6789=3>85fnrv\eis({}kSkh_bcqv|Yj}q:;<=Qbaq3460=nfz~Tma{ sucw[wc`Wjky~tQbuy2345Yjiy;3>85fnrv\eis({}kSkh_bcqv|Yj}q:;<=Qbaq3:60=nfz~Tma{ sucw[wc`Wjky~tQbuy2345Yjiy89=k5fnrv\eis({}kSkh_bcqv|Yig}:;<<>10g8mkusWhf~#~znt^pfcZ|bzfUfyu>?0103?lht|Vkgy"}{au]qabY}m{eTaxv?01225779;90ec}{_`nv+vrf|VxnkRtjrn]nq}6789;2Sk;=0:kmwqYfd|%xxlzPrde\~`thWds<=>?3501?lht|Vkgy"}{au]qabY}m{eTaxv?012;0475<2ceyQnlt-ppdrXzlmTvh|`_lw{45670=;Tj8<;;hlppZgk}&ymyQ}ef]yawiXe|r;<=>Pm`r2275oi{}Uj`x!|ul]qav:56890ec}{_`nv+vsjW{ox0>0>3:kmwqYfd|%xy`Q}er>7:45018mkusWhf~#~{b_sgp8286=2ceyQlhhrqeh)JzhgT^LC=1:kmwqYd``zyij!ltsn\kpr)kdofSeghh^215>oi{}Uhdd~}ef-`pwjXg|~%o`kb_ikdlZ7592ceyQlhhrqab)d|{fTcxz!clgn[mo``V89=6gasu]`llvumn%hxbPotv-ghcjWacldR==8:kmwqYd``zyij!ltsn\kpr)ag~Toy|c.dfdaZubfz8>7d`|t^akmutbo&i~aQ`uu,jjqYd|{f%icomld04?lht|Vice}|jg.awviYh}}$bbyQltsn-tjjfz`~r>;5fnrv\gmowzlm$oy|c_nww*lhsWj~y`#|jqtgpp760ec}{_bjjtwc`'me~x1=1159jjvrXkac{~hi dnww8186<2ceyQlhhrqab)cg|~793?;;hlppZeoayxnk"j`uu>4:45oi{}Uhdd~}ef-gkprX?830ec}{_bjjtwc`'me~xRoad12344e?1=2=5a=nfz~Toegrde,`jssWds<=>><1<25f=nfz~Toegrde,`jssWds<=>><3<2`>oi{}Uhdd~}ef-gkprXe|r;<=?32?32g>oi{}Uhdd~}ef-gkprXe|r;<=?34?03?lht|Vice}|jg.flqqYj}q:;<<2;>^QT44e?1=7=65=nfz~Toegrde,`jssWds<=>><4<\WR6582ceyQlhhrqab)cg|~Taxv?013?1;YT_8;n7d`|t^akmutbo&ndyyQbuy2344:16;29>6gasu]`llvumn%ocxzPmtz3457;>783S^Y?1d9jjvrXkac{~hi dnww[hs89::0;0;9308mkusWjbb|kh/emvpZkrp9:;=181_lcs51463`dxxRmgiqpfc*bh}}Ufyu>?00>5:Zkfx1;o7d`|t^akmutbo&ndyyQbuy2344:068;n7d`|t^akmutbo&ndyyQbuy2344:068=:h6gasu]`llvumn%ocxzPmtz3457;?7=:i6gasu]`llvumn%ocxzPmtz3457;?7=:>?5fnrv\gmowzlm$hb{{_lw{45664>4<=R]X0338mkusWjbb|kh/emvpZkrp9:;=191_lcs574?1=5=[hgw908:7d`|t^akmutbo&ndyyQbuy2344:06Vgj|9<>;hlppZeoayxnk"j`uu]nq}67886<2Rcnp63g?lht|Vice}|jg.pfcZejmdUcejf30?3g?lht|Vice}|jg.pfcZejmdUcejf31?3g?lht|Vice}|jg.pfcZejmdUcejf32?3g?lht|Vice}|jg.pfcZejmdUcejf33?3`?lht|Vice}|jg.pfcZejmdUcejfP0318mkusWjbb|kh/sgd[fkbeVbbkeQ?_sqwtjr6k2ceyQlhhrqab)umnUhahcPhhek[4443`dxxRmgiqpfc*tboVifi`Qgifj\5Ztt|ye=n5fnrv\gmowzlm$~hiPclgn[mo``V89?6gasu]`llvumn%yijQlmdo\llaoW;Uyy~`t0a8mkusWjbb|kh/sgd[fkbeVbbkeQ<229jjvrXkac{~hi rde\ghcjWacldR=Prrvskq4?3`dxxRmgiqpfc*tboVifi`Qgifj\jjr789;:=R]X03:8mkusWjbb|kh/sgd[fkbeVbbkeQaou234476WZ]:>:5fnrv\gmowzlm$~hiPclgn[mo``Vddx=>?13]PS5403`dxxRmgiqpfc*tboVifi`Qgifj\jjr789;9S^Y>269jjvrXkac{~hi rde\ghcjWacldR``t12357YT_;8<7d`|t^akmutbo&xnkRmbel]kmbnXff~;<=?=_RU066=nfz~Toegrde,v`aXag~Toy|c.dfdaZubfz8j7d`|t^akmutbo&xnkRgat^awvi(blnoTh`|_sqwtjr582ceyQlhhrqab)umnUbbyQltsn-akgedl8<7d`|t^akmutbo&xnkRgat^awvi(bfhhgiR||tqmw67=nfz~Toegrde,v`aXag~Toy|c.qmoewosq;30ec}{_bjjtwc`'{olSd`{_bvqh+vhdhxbxtQ}surlp77h5fnrv\gmowzlm$~hiPiov\gqtkW{ozyh}{_lw{45659VY\=?k4ioqw[fnnx{ol#kh_hlw[frudVxn}xk|t^ov|567:8UX[???PSV01e>oi{}Uhdd~}ef-qabYnf}UhxbPrdsvavrXe|r;<=<<1b9jjvrXkac{~hi rde\tdabWzog0=0>b:kmwqYd``zyij!}ef]sebcX{lfTb:kmwqYd``zyij!}ef]ppnYoanbT>?<4ioqw[fnnx{ol#kh_rvh[mo``V8T~~zou3a?lht|Vice}|jg.pfcZuscVbbkeQ<239jjvrXkac{~hi rde\wqmX``mcS>Q}surlp70?003\WR75>2ceyQlhhrqab)umnUxxfQgifj\jjr789;:S^Y=279jjvrXkac{~hi rde\wqmX``mcSca{01225ZUP;8>0ec}{_bjjtwc`'{ySd`y1c9jjvrXkac{~hi rrv\mkp6W@D]S=<=;hlppZbwi}bToy|c/LpliZh789:T~bc?01210>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567998>7d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=>>000;?lht|Vn{myfPcupo+HtheVd;<=>Prno3456688;:=?64ioqw[avf|aUhxb Msmn[k6789Uyc`>?01335475:h1bb~zPdqcwlZesze%F~bcPn1234Zthe9:;<<>>10]e171?01]qkh6789;;=<<=8:kmwqYcxh~cSnz}l.OqkhYi89:;Sab01235576:88=7d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=>>1031<>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn45679:;:;5?0130541?WZ]:>;5fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?004257g?01]qkh6789;==Prno34566>8;T_Z==8:kmwqYcxh~cSnz}l.OqkhYi89:;Sab0123657691837d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=>=003667>?01]qkh67898;=<6=299jjvrXlykdRm{rm-NvjkXf9:;?2132=<4d3`dxxRjauj\gqtk'DxdaR`?012\vjk789:9<?01]qkh67898;=?0^pli5678;::=Rcnp3:1g>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567:9;:S`o280a?lht|Vn{myfPcupo+HtheVd;<=>Prno3456588;Tal~7299jjvrXlykdRm{rm-NvjkXf9:;;9h6gasu]gtdroWj~y`"C}ol]m4567W{ef<=>?223234YT_9;9j6gasu]gtdroWj~y`"C}ol]m4567W{ef<=>?223234YT_9Um9?m4ioqw[avf|aUhxb Msmn[k6789Uyc`>?01005416WZ]:>;5fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?034257g?01]qkh67898==Prno34565>8;T_Z?=6:kmwqYcxh~cSnz}l.OqkhYi89:;Sab01236=76:h1bb~zPdqcwlZesze%F~bcPn1234Zthe9:;1^QT570?01]qkh67899:=<?3032[VQ6:?1bb~zPdqcwlZesze%F~bcPn1234Zthe9:;<>:>13:8mkusWmzjxeQltsn,IwijWg:;<=Q}ol23455398;:>55fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?0262577502ceyQkp`vk[frud&Gyc`Qa0123[wij89:;?9?>300b?lht|Vn{myfPcupo+HtheVd;<=>Prno34564<8;T_Z>=a:kmwqYcxh~cSnz}l.OqkhYi89:;Sab01237176WZ]:>95fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?05211>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567<8;956gasu]gtdroWj~y`"C}ol]m4567W{ef<=>?403\WR65<2ceyQkp`vk[frud&Gyc`Qa0123[wij89:;8>?423\37d?01]qkh6789>8=R9PSV213>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567<:;T4?:4ioqw[avf|aUhxb Msmn[k6789Uyc`>?016661=nfz~Th}o{h^awvi)JzfgTb=>?0^pli5678=<986gasu]gtdroWj~y`"C}ol]m4567W{ef<=>?4607?lht|Vn{myfPcupo+HtheVd;<=>Prno345630;?0ec}{_erbpmYd|{f$Aab_o2345Yugd:;<=:713c8mkusWmzjxeQltsn,IwijWg:;<=Q}ol23452?9V8Tj;?493\07g?01]qkh6789>3=R:Pf404?lht|Vn{myfPcupo+HtheVd;<=>Prno3456308U>>55fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?05:2[075?2ceyQkp`vk[frud&Gyc`Qa0123[wij89:;85?P6378mkusWmzjxeQltsn,IwijWg:;<=Q}ol23452>9;?0ec}{_erbpmYd|{f$Aab_o2345Yugd:;<=;?1378mkusWmzjxeQltsn,IwijWg:;<=Q}ol2345369;=0ec}{_erbpmYd|{f$Aab_o2345Yugd:;<=;>10312>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567=<;:>55fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?04725475i2ceyQkp`vk[frud&Gyc`Qa0123[wij89:;98?>_RU363=nfz~Th}o{h^awvi)JzfgTb=>?0^pli5678<3:=?64ioqw[avf|aUhxb Msmn[k6789Uyc`>?017:5476:h1bb~zPdqcwlZesze%F~bcPn1234Zthe9:;<87>1^QT471?01]qkh6789<<=3`dxxRjauj\gqtk'DxdaR`?012\vjk789:=;Prno3456088;9;6gasu]gtdroWj~y`"C}ol]m4567W{ef<=>?763257??01]qkh67892;=<:>13`8mkusWmzjxeQltsn,IwijWg:;<=Q}ol2345>798>:Sk;=7:kmwqYcxh~cSnz}l.OqkhYi89:;Sab0123<576?;20ec}{_erbpmYd|{f$Aab_o2345Yugd:;<=6?10::6f=nfz~Th}o{h^awvi)JzfgTb=>?0^pli56781::=Rcnp061f>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn456709;:S`o33g8mkusW`dSnz}l.O{kwYnf}Uxm`~cee]{kw6789UYi~{ct035?lht|VcexRm{rm-jjqYfkb;:56gasu]jjqYd|{f$eczPs`osh`b592ceyQfnu]`pwj(ag~Tlcldf\|jt789::o6gasu]jjqYd|{f$eczPsucwaZ@Al8;m7d`|t^kmpZesze%bbyQ|t`vf[C@c9$Ce>=5fnrv\mkrXk}xg#d`{_rvbp`YANm;&Ec?>c:kmwqYnf}Uhxb iov\wqgsmVLMh??i;hlppZoi|Vi~a!fnu]ppdrbWOLo> Ga209jjvrXag~Toy|c/hlw[vrf|lUMJi<"Io0264=nfz~TeczPcupo+lhsWz~jxhQIFe0.Mk26:?1bb~zPiov\gqtk'`dS~zntd]EBa4*Ag>:S^Y?1348mkusW`dSnz}l.kmpZusi}oTJKj=-Hl75ZUP8;837d`|t^kmpZesze%bbyQ|t`vf[C@c:$Ce8;hlppZoi|Vi~a!io]ppdrbWOLo> Ga_G02?lht|VcexRm{rm-smkYt|h~nSKHk2,Km[B7e3`dxxRgat^awvi)t|h~T~h}{_nww5g=nfz~TeczPcupo+vrf|VyjzhQ`uu35?lht|VcexRm{rm-ppnYwgy;:;6gasu]jjqYd|{f$yePptqk577Pcx>1:72<5fnrv\tf)JimnTz}mPaefpqg6789Uhu1=1259jjvrXxj%FmijPvqa\eabt}k:;<=Qly=1=[wr592ceyQc.Ob`aYqxjUjhi}zb1234Ze~4=4986gasu]sg*KflmU}|nQndeqvf5678Vir090Pru02?lht|Vzh#@okd^tsgZgclzi<=>?_b{?1;433`dxxR~l/Lcg`ZpwkVkoh~{m0123[f;=7Uyx??4ioqw[ue(EhnoS{~l_`fgwpd789:Tot29>368mkusWyi$Aljk_wr`[dbc{|h;<=>Pcx>5:Zts:81bb~zPpb-NeabX~yiTmij|uc2345Ydq5=5>95fnrv\tf)JimnTz}mPaefpqg6789Uhu191_sv15>oi{}U{o"Cnde]utfYflmy~n=>?0^az8=85<2ceyQc.Ob`aYqxjUjhi}zb1234Ze~414T~y<>;hlppZvd'DkohRxc^cg`vse89:;Snw39?07?lht|Vzh#@okd^tsgZgclzi<=>?_b{?=;Yu|;20ec}{_qa,IdbcWzhSljkst`3456Xd|~7<3QFNW]366=nfz~T|n!Baef\rueXimnxyo>?01]{kw:687887d`|t^r`+HgclV|{oRokdrwa4567Wqey025;Yu|;80ec}{_qa,IdbcWzhSljkst`3456Xpfx7=3<=;hlppZvd'DkohRxc^cg`vse89:;Sua}<3<16>oi{}U{o"Cnde]utfYflmy~n=>?0^zlv959:;1bb~zPpb-NeabX~yiTmij|uc2345Yg{6?2?<4ioqw[ue(EhnoS{~l_`fgwpd789:Ttb|35?01?lht|Vzh#@okd^tsgZgclzi<=>?_ymq8385:2ceyQc.Ob`aYqxjUjhi}zb1234Z~hz5=5>?5fnrv\tf)JimnTz}mPaefpqg6789Usc27>308mkusWyi$Aljk_wr`[dbc{|h;<=>Pxnp?=;goi{}U{o"~l_og{p9799;1bb~zPpb-sgZhbp}692<<4ioqw[ue(xjUeiuz33?31?lht|Vzh#}mPndzw8186:2ceyQc.r`[kc|5?5=?5fnrv\tf)wkVdnty29>008mkusWyi$|nQaeyv?3;753`dxxR~l/qa\j`~s414:>6gasu]sg*vdWgosx171109jjvrXxj%{oR`jxu]354=nfz~T|n!c^lf|qY69;1bb~zPpb-sgZhbp}U:<<<4ioqw[ue(xjUeiuzP1032?lht|Vzh#}mPndzw[7763`dxxR~l/qa\j`~sW:;:7d`|t^r`+ueXflrS9?>;hlppZvd'yiTbhv{_432?lht|Vzh#}mPndzw[3763`dxxR~l/qa\j`~sW>;:7d`|t^r`+ueXflrS5?>;hlppZvd'yiTbhv{_83;?lht|Vzh#}mPndzw[dhc89:;==?;;hlppZvd'zh0=0=0^QT4463:kmwqYwk&|{o1?>>^QT4`=nfz~T|n!ypb>2:440>2:kmwqYwk&|{o1=1_RU1a>oi{}U{o"xc=6=57=nfz~T|n!ypb>7:ZUP:l1bb~zPpb-utf:26880ec}{_qa,rue;=7UX[?k4ioqw[ue(~yi7:3?=;hlppZvd'zh0;0PSV0f?lht|Vzh#{~l<6<26>oi{}U{o"xc=5=[VQ5m2ceyQc.tsg9>99;1bb~zPpb-utf:?6VY\>h5fnrv\tf)qxj622<<4ioqw[ue(~yi753Q\W33b?lht|Vzh#{~l_`fgwpd789:7==0>a:kmwqYwk&|{oRokdrwa456748;5=45fnrv\tf)qxjUjhi}zb1234979901bb~zPpb-utfYflmy~n=>?0=0=5<=nfz~T|n!ypb]b`aurj9:;<1=1189jjvrXxj%}|nQndeqvf56785>5=45fnrv\tf)qxjUjhi}zb1234939901bb~zPpb-utfYflmy~n=>?0=4=5<=nfz~T|n!ypb]b`aurj9:;<191189jjvrXxj%}|nQndeqvf5678525=45fnrv\tf)qxjUjhi}zb12349?9981bb~zPpb-utfYumnU;=<5fnrv\tf)qxjUyijQ>139jjvrXxj%}|nQ}ef]2444;hlppZvd'zhSkh_232?lht|Vzh#{~l_sgd[1763`dxxR~l/wr`[wc`W<;:7d`|t^r`+svdW{olS;?>;hlppZvd'zhSkh_632?lht|Vzh#{~l_sgd[=763`dxxR~l/wr`[wc`W0;=7d`|t^r`+svdW{olSb|?0122<>oi{}U{o"xc^pfcZiu89:;?;?l;hlppZvd'zhSkh_np34564>VY\<?_lcs56473`dxxR}{abi\gqtk'DidyczPpup\g|:76;:0ec}{_rvbgnYd|{f$Anaznu]spwYdq5;5>=5fnrv\wqgdcVi~a!BcnwmpZvszVir0?0=0:kmwqYt|hi`Snz}l.O`kphsWy~ySnw33?03?lht|VymnePcupo+Heh}g~T|y|Pcx>7:76;hlppZusijaToy|c/LalqkrXx}xT`xz30?02?lht|VymnePcupo+Heh}g~T|y|Pltv?5;463`dxxR}{abi\gqtk'DidyczPpup\hpr;:78:7d`|t^qwefmXk}xg#@m`uov\tqtXd|~7?3<>;hlppZusijaToy|c/LalqkrXx}xT`xz34?02?lht|VymnePcupo+Heh}g~T|y|Pltv?1;463`dxxR}{abi\gqtk'DidyczPpup\hpr;>78:7d`|t^qwefmXk}xg#@m`uov\tqtXd|~7;3<>;hlppZusijaToy|c/LalqkrXx}xT`xz38?02?lht|VymnePcupo+Heh}g~T|y|Pxnp?4;463`dxxR}{abi\gqtk'DidyczPpup\|jt;978:7d`|t^qwefmXk}xg#@m`uov\tqtXpfx7>3<>;hlppZusijaToy|c/LalqkrXx}xTtb|33?02?lht|VymnePcupo+Heh}g~T|y|Pxnp?0;463`dxxR}{abi\gqtk'DidyczPpup\|jt;=78:7d`|t^qwefmXk}xg#@m`uov\tqtXpfx7:3<>;hlppZusijaToy|c/LalqkrXx}xTtb|37?02?lht|VymnePcupo+Heh}g~T|y|Pxnp?<;703`dxxR}{abi\gqtk'me~x1>1199jjvrX{}khgRm{rm-gkpr;994:46gasu]ppdelWj~y`"j`uu>25;703`dxxR}{abi\gqtk'me~x1?1169jjvrX{}khgRm{rm-gkpr;:7;<7d`|t^qwefmXk}xg#iazt=1=52=nfz~Tyolk^awvi)cg|~783?8;hlppZusijaToy|c/emvp9399>1bb~zPsuc`oZesze%ocxz36?34?lht|VymnePcupo+air|5=5=:5fnrv\wqgdcVi~a!kotv?<;703`dxxR}{abi\gqtk'me~x171179jjvrX{}khgRm{rm-gkprX88<0ec}{_rvbgnYd|{f$hb{{_034?lht|VymnePcupo+air|V;;=:5fnrv\wqgdcVi~a!kotv\54713`dxxR}{abi\gqtk'me~xR<>6:kmwqYt|hi`Snz}l.flqqY49?1bb~zPsuc`oZesze%ocxzP4048mkusWz~jofQltsn,`jssW<;=7d`|t^qwefmXk}xg#iazt^422>oi{}Uxxlmd_bvqh*bh}}U<=;5fnrv\wqgdcVi~a!kotv\<402ceyQ|t`ah[frud&z~1>1179jjvrX{}khgRm{rm-spw:668<0ec}{_rvbgnYd|{f$|y|32?35?lht|VymnePcupo+uru4:4::6gasu]ppdelWj~y`"~{r=6=53=nfz~Tyolk^awvi)w|{6>2<84ioqw[vrfkbUhxb pup?2;713`dxxR}{abi\gqtk'y~y0:0>6:kmwqYt|hi`Snz}l.rwv9>99<1bb~zPsuc`oZesze%{xQ?149jjvrX{}khgRm{rm-spwY69<1bb~zPsuc`oZesze%{xQ=149jjvrX{}khgRm{rm-spwY49<1bb~zPsuc`oZesze%{xQ;149jjvrX{}khgRm{rm-spwY29<1bb~zPsuc`oZesze%{xQ9149jjvrX{}khgRm{rm-spwY09<1bb~zPsuc`oZesze%{xQ71c9jjvrX{}khgRm{rm-spwYig}:;<0:kmwqtXimny01?f8mkuszVkoh2>>e9jjvruWhno~1<1d:kmwqtXimny0>0k;hlppwYflmx783j4ioqwvZgcl{6>2i5fnrvq[dbcz5<5h6gasup\eabu4>4o7d`|ts]b`at;07n0ec}{r^cg`w:>6j1bb~z}_ekm858c3`dxxQkio>24;boi{}xThd`3124?f8mkuszVnbb1?:>e9jjvruWmce0<81f:kmwqtXl`d7=:4?>e9jjvruWmce0<91c:kmwqtXl`d7=3m4ioqwvZbnf585o6gasup\`lh;;7i0ec}{r^fjj929k2cey|Pdhl?1;eoi{}xThd`37?a8mkuszVnbb161c:kmwqtXl`d75394iov\efm13`dSd`m;hlw[vrlWye{o6gat^qwoZvr{a<0ebQ|em58munf{l;27d~garg?4;>>7:ksldubW9Ufyu>?013\MKPX8k1fi`Qndep?4;`2:a=jmdUjhi|31?]2b>kbeVkoh2>>^QT4c=jmdUjhi|31?]PS4dkbeVkoh2<>0a8i`kXimny0>0=e:ofiZgcl{682Rh:b:ofiZgcl{6?2k5bel]b`at;<7UX[=h4mdo\eabu4=4T_Z?l;lgn[dbcz5?5=n5bel]b`at;=78n7`kb_`fgv939Wo?h7`kb_`fgv9099j1fi`Qndep?2;4b3dofSljkr=4=[c3d3dofSljkr=5=5f=jmdUjhi|37?0f?hcjWhno~191_g7`?hcjWmkm1>11b9nahYci}k7=3?l;lgn[agsi585=n5bel]geqg;;7;h7`kb_ecwe9299j1fi`Qkauc?1;7d3dofSio{a=4=5f=jmdUomyo37?3b?ueXag6;22:a=umnUiSiazt=0=`>tboVhThb{{<2e9qabYeWme~x181d:pfcZdXlf0:0n;sgd[aoi494j7kh_ekm848f3{olSiga<30n;sgd[aoi4=4j7kh_ekm808f3{olSiga<72:pfcZbnfVg~t=>?0=2=56=umnUoecQbuy2345:768;97kh_ekm[hs89:;0<0>3:pfcZbnfVg~t=>?0=3=544139qabYcagUfyu>?01>0:456|jg^fjjZkrp9:;<1:1129qabYcagUfyu>?01>7:4753{olSiga_lw{45674<4:?6|jg^fjjZkrp9:;<1;11008v`aXl`dTaxv?012?2;743{olSiga_lw{45674?4:=?5}ef]gmkYj}q:;<=28>018v`aXl`dTaxv?012?3;743{y=95|t`vvwZtbo'kgy#mnrs{27>usi}xSkh.`nv*cug01xxfQfn=2=f>uscVce0=0PFc9ppnYnf5:5SJo4sui\mk:687h0yePio>24;7c3z~`Sd`311<\b0g<{}aTec2>1?`8wqmXag6:=3?k;rvh[lh;984Tj874sui\mk:66k1xxfQfn=3=[Cd<{}aTec2>>^E:?vrlW`d7>3l4sui\mk:56VLi7~zd_hl?6;Y@12ygRga<22o5|tj]jj939WOh0yePio>6:ZA>3z~`Sd`36?`8wqmXag6=2RHm;rvh[lh;>7UL56}{k^km828e3z~`Sd`37?]Ef>uscVce0:0PG89ppnYnf525m6}{k^km8=86k2ygRga<9<\b0?<{}aTec26>`9ppnYnf535=n5|tj]jj9?9Wo?n7~zd_hl\ekb789:m7~zd_hl\ekb789::m6}{k^mvp969j2ygRazt=33:g=t|bUdyy2>1?c8wqmXg|~7=3o4sui\kpr;:7k0yePotv?7;g<{}aTcxz34?c8wqmXg|~793o4sui\kpr;>7k0yePotv?3;g<{}aTcxz38?c8wqmXg|~75364sui\tpuoi2ygR~zsi32e>uscVz~e<<9:qwoZvr{a>27~zd_qwpl2b<{}aT|x}g_lcs6a=t|bU{y~fPm`r7<>qf{Vzh`io4w`q\tjv5xj;:7um;vrz01(77%ol=:5?<;ykl[vckWjg{Sh?0122g>~jmdUjhi|30?a8|hcjWhno~1?1c:znahYflmx7>3m4xlgn[dbcz595o6vbel]b`at;<7i0t`kb_`fgv939k2rfi`Qndep?2;c~jmdUoec2?>c9{i`kXl`d7=3l4xlgn[aoi4;4i7ucjm^fjj959j2rfi`Qkio>7:g=elgThd`35?`8|hcjWmce0;0k;yofiZbnf5=1<3l4xlgn[aoi4>4h7ucjm^flqq:76j1sahcPdnww848d3qgnaRj`uu>1:f=elgThb{{<2<`?}kbeVndyy2;>b9{i`kXlf080l;yofiZbh}}6=2h5wmdo\`jss4>0;2n5wmdo\`jss4>4<7ucjm^pf<>~jmdUyi<94xlgn[rc?3qgnaRyj1|BCt452i2JKt>;::G81>4}T1h08=84>cc827725l=0:hn78{o127?7?::0aa>455<;n?697>51;396d?|[0k1?<;51b`95643:m>1=im69:&1bg<6kl1/>i7568a8f6322908i7<92;0b=~N5n01/>k653478^=1==r>n69j51c82b?2d2te=<84?::k00<<722c88;4?::k51`<722e=n44?::m54<<722e=no4?::k543<722e=n54?:%0gf?0e?2d9hl4?;:m5f3<72-8on78m7:l1`d<632e=n84?:%0gf?0e?2d9hl4=;:m5f1<72-8on78m7:l1`d<432e=n>4?:%0gf?0e?2d9hl4;;:m5f7<72-8on78m7:l1`d<232e=n<4?:%0gf?0e?2d9hl49;:m5f5<72-8on78m7:l1`d<032e=m;4?:%0gf?0f=2d9hl4?;:m5e1<72-8on78n5:l1`d<632e=m>4?:%0gf?0f=2d9hl4=;:m5e7<72-8on78n5:l1`d<432e=m<4?:%0gf?0f=2d9hl4;;:m5e5<72-8on78n5:l1`d<232e=5k4?:%0gf?0f=2d9hl49;:m5=`<72-8on78n5:l1`d<032e>i54?:%0gf?3b?2d9hl4?;:m6a3<72-8on7;j7:l1`d<632e>j<4?:%0gf?3b?2d9hl4=;:m6b5<72-8on7;j7:l1`d<432e>ik4?:%0gf?3b?2d9hl4;;:m6a`<72-8on7;j7:l1`d<232e>ii4?:%0gf?3b?2d9hl49;:m6af<72-8on7;j7:l1`d<032e>io4?:%0gf?3b?2d9hl47;:m6ad<72-8on7;j7:l1`d<>32e>i44?:%0gf?3b?2d9hl4n;:m6a0<72-8on7;j7:l1`djo4?:%0gf?3ai2d9hl4?;:k6b<<72-8on7;ia:l1`d<632c>j54?:%0gf?3ai2d9hl4=;:k6b2<72-8on7;ia:l1`d<432c>j;4?:%0gf?3ai2d9hl4;;:k6b0<72-8on7;ia:l1`d<232c>j94?:%0gf?3ai2d9hl49;:k6b6<72-8on7;ia:l1`d<032c=<94?:%0gf?3ai2d9hl47;:k546<72-8on7;ia:l1`d<>32c=jh4?:%0gf?3ai2d9hl4j;:k6ba<72-8on7;ia:l1`djn4?:%0gf?3ai2d9hl4>0:9j1c4=83.9ho4:f`9m6ag=9810e;oi:18'6ad=>ho0b?jn:198m3gc290/>il56`g8j7bf2810e;ol:18'6ad=>ho0b?jn:398m3ge290/>il56`g8j7bf2:10e;on:18'6ad=>ho0b?jn:598m3g>290/>il56`g8j7bf2<10e;o7:18'6ad=>ho0b?jn:798m3g0290/>il56`g8j7bf2>10n>?>:182>5<7s-8m4750z&1b=<6?>1C?=h4H3d:?j70>3:17pl90b83>0<729q/>k651738L66a3A8m56*>8483?l>?2900e4<50;9j==<722c2n7>5;n0g`?6=3th89;4?:583>5}#:o21=;>4H22e?M4a12c347>5;h;;>5<6F<0g9K6c?>o>j3:17b90;694?:1y'6c>=9?80D>>i;I0e=>o?03:17d7=:188mij50;9~f0b7290?6=4?{%0e=831b554?::k:f?6=3f8oh7>5;|`6g2<72<0;6=u+2g:9537<@::m7E>{e=j<1<7;50;2x 7`?28<:7E=?f:J1b<=n010;66g62;29?l??2900e4l50;9l6ab=831vn8mi:186>5<7s-8m47?91:J04c=O:o30e5650;9j=7<722c247>5;h;a>5<5<>o>j3:17b=9?;0D>>i;I0e=>o?03:17d7=:188m<>=831b5o4?::m1`a<722wi9nm50;794?6|,;l36<8>;I13b>N5n01b454?::k:6?6=3`336=44i8`94?=h:mn1<75rb4aa>5<2290;w)N48o1C>k74i9:94?=n1;0;66g68;29?l?e2900c?jk:188yg3di3:197>50z&1b=<6>81C?=h4H3d:?l>?2900e4<50;9j==<722c2n7>5;n0g`?6=3th>o44?:483>5}#:o21=;?4H22e?M4a12c347>5;h;1>5<>i5lm0;66sm5b:94?3=83:p(?h7:042?M57n2B9j45f8983>>o>:3:17d77:188mij50;9~f0e2290>6=4?{%0e=831b5?4?::k:5<55;294~"5n10::<5G31d8L7`>3`236=44i8094?=n110;66g6b;29?j4cl3:17pl:0e83>6<729q/>k6514d8L66a3A8m56g78;29?l?e2900c?jk:188yg35;3:1?7>50z&1b=<6=o1C?=h4H3d:?l>?2900e4l50;9l6ab=831vn8<;:180>5<7s-8m47?:f:J04c=O:o30e5650;9j=g<722e9hi4?::a14`=83>1<7>t$3d;>4073A9;j6F=f89'5=3=82c347>5;h;;>5<6=5f8983>>o>03:17d7m:188k7bc2900qo;>2;290?6=8r.9j54>619K75`<@;l27)?75;28m=>=831b554?::k:f?6=3f8oh7>5;|`64c<72=0;6=u+2g:9536<@::m7E>{e<=?1<7m=:183!4a038n<6F<0g9K6c?;537803?4f2;h1?54<9;'5=5=;2.:494<;%13=?5702.8h:5139m75d=9;1e?=m5139m55`=82d:?<4?;%0e5?72k2.9i?4=d79'6c2=92.:4;4<;%3;3?5<,8236>5+19;97>"60h087)?7b;18 4>d2:1/=5j53:&2<`<43-;3j7=4$0;3>6=#90;1?6*>9380?!7>;390(<7;:29'5<3=;2.:5;4<;%3:3?5<,8336>5+18;97>"61h087)?6b;18 4?d2:1/=4j53:&2=`<43-;2j7=4$0c3>6=#9h;1?6*>a380?!7f;390(5+1`;97>"6ih087)?nb;18 4gd2:1/=lj53:&2e`<43-;jj7=4$0`3>6=#9k;1?6*>b380?!7e;390(5+1c;97>"6jh087)?mb;18 4dd2:1/=oj53:&2f`<43-;ij7=4$0a3>6=#9j;1?6*>c380?!7d;390(5+16g97>"6?o087)?70;18 4>62:1/=5<53:&2g<<6=j1/=no514a8 7c62;n=7)5<6=44i3g5>5<5<5$3fa>33o193:1(?jm:778j7bf2=10e;h50;&1`g<1=2d9hl4:;:k5a?6=,;ni6;;4n3fb>3=h5lh0<76g9c;29 7be2??0b?jn:998m3d=83.9ho495:l1`d<>32c=m7>5$3fa>33o103:1(?jm:778j7bf2j10e;950;&1`g<1=2d9hl4k;:k54?6=,;ni6;;4n3fb>`=<1<7*=dc841>h5lh0;76g84;29 7be2>?0b?jn:098m25=83.9ho485:l1`d<532c<>7>5$3fa>2354i6394?"5lk0<96`=d`87?>o0n3:1(?jm:678j7bf2<10e:k50;&1`g<0=2d9hl49;:k4`?6=,;ni6:;4n3fb>2=i1<7*=dc841>h5lh0376g8b;29 7be2>?0b?jn:898m2g=83.9ho485:l1`d5$3fa>23o0?3:1(?jm:678j7bf2m10e:>50;&1`g<0=2d9hl4j;:kaf?6=,;ni6oo4n3fb>5=h5lh0:76gm7;29 7be2kk0b?jn:398mg0=83.9ho4ma:l1`d<432ci97>5$3fa>ggoe;3:1(?jm:cc8j7bf2?10eo<50;&1`g==h5lh0276gnf;29 7be2kk0b?jn:`98mdc=83.9ho4ma:l1`d5$3fa>ggofi3:1(?jm:cc8j7bf2l10el750;&1`g46<3`k<6=4+2e`9fd=i:mk1=<54i`494?"5lk0im6`=d`826>=ni<0;6)il5b`9m6ag=9<10en<50;&1`g6:9jg4<72-8on7ln;o0ge?7032ch<7>5$3fa>gg5<#:mh1nl5a2ec95<=h5lh0:m65fbe83>!4cj3hj7coek3:1(?jm:cc8j7bf28i07dl7:18'6ad=jh1e>io51e98mdb=83.9ho4ma:l1`d<6m21bm?4?:%0gf?df3g8om7?i;:kgg?6=,;ni6il4n3fb>5=h5lh0:76gk8;29 7be2mh0b?jn:398ma1=83.9ho4kb:l1`d<432co:7>5$3fa>adoc<3:1(?jm:e`8j7bf2?10ei=50;&1`g==h5lh0276gk0;29 7be2mh0b?jn:`98mf`=83.9ho4kb:l1`d5$3fa>adodj3:1(?jm:e`8j7bf2l10eno50;&1`g46<3`i36=4+2e`9`g=i:mk1=<54ib594?"5lk0on6`=d`826>=nk?0;6)il5dc9m6ag=9<10eh=50;&1`g6:9ja7<72-8on7jm;o0ge?7032cn=7>5$3fa>ad5<#:mh1ho5a2ec95<=h5lh0:m65fdd83>!4cj3ni7cocl3:1(?jm:e`8j7bf28i07dj6:18'6ad=lk1e>io51e98mfc=83.9ho4kb:l1`d<6m21bo>4?:%0gf?be3g8om7?i;:kf5=h5lh0:76gj5;29 7be2l=0b?jn:398m`2=83.9ho4j7:l1`d<432cnh7>5$3fa>`eobi3:1(?jm:da8j7bf2;10eh750;&1`g;:k1bc<72-8on7=?1:l1`d<532c9jh4?:%0gf?5792d9hl4<;:k042<72-8on7=?6:l1`d<732c8<84?:%0gf?57>2d9hl4>;:k041<72-8on7=?6:l1`d<532c8<>4?:%0gf?57>2d9hl4<;:m242<72-8on7??6:l1`d<732e:<84?:%0gf?77>2d9hl4>;:m246<72-8on7??6:l1`d<532e:2d9hl4<;:m244<72-8on7??6:l1`d<332e:<=4?:%0gf?77>2d9hl4:;:meb?6=,;ni6<>9;o0ge?0<3fln6=4+2e`9550=hnj0;6)h5lh0276aib;29 7be28:=7cil51148j7bf2k10ck650;&1`g<68?1e>io5c:9lb2<72-8on7??6:l1`d5$3fa>4613g8om7k4;nd6>5<#:mh1==84n3fb>c=1<7*=dc8243=i:mk1==54og194?"5lk0:<;5a2ec954=9;o0ge?7032e:2d9hl4>8:9l55d=83.9ho4>079m6ag=9010c<>n:18'6ad=99<0b?jn:0c8?j7713:1(?jm:025?k4ci3;i76a>0983>!4cj3;;:6`=d`82g>=h99>1<7*=dc8243=i:mk1=i54og;94?"5lk0:<;5a2ec95`=5<#:mh1=?64n3fb>5=5<#:mh1=?64n3fb>7=54o000>5<#:mh1=?64n3fb>1=5<#:mh1=?64n3fb>3=5<#:mh1=?64n3fb>==5<#:mh1=?64n3fb>d=5<#:mh1=?64n3fb>f=5<#:mh1=?64n3fb>`=5<#:mh1=?64n3fb>46<3f;:97>5$3fa>44?3g8om7?>;:m251<72-8on7?=8:l1`d<6:21d=<=50;&1`g<6:11e>io51298k475290/>il513:8j7bf28>07b?>1;29 7be28837ci6;90;6)h5lh0::65`13d94?"5lk0:>55a2ec952=32e:>n4?:%0gf?7502d9hl4>a:9l57d=83.9ho4>299m6ag=9k10c<3:1(?jm:00;?k4ci3;o76a>1c83>!4cj3;946`=d`82a>=h98:1<7*=dc826==i:mk1=k54o015>5<#:mh1=>;4n3fb>5=5<#:mh1=>;4n3fb>7=54o01a>5<#:mh1=>o4n3fb>5=5<#:mh1=>o4n3fb>7=54}c16=?6=l3:15<>o2=3:17d7m:188m45c2900e<=j:188m45a2900e<:?:188m7`d2900e?hk:188k7`42900c<=l:188yg52i3:1h7>50z&1b=<5lo1C?=h4H3d:?l352900e8=50;9j11<722c>97>5;h;a>5<5<5<5<5<n7>5d;294~"5n109hk5G31d8L7`>3`?96=44i4194?=n==0;66g:5;29?l?e2900e<=k:188m45b2900e<=i:188m4272900e?hl:188m7`c2900c?h<:188k45d2900qo=:e;29`?6=8r.9j54=dg9K75`<@;l27d;=:188m05=831b994?::k61?6=3`3i6=44i01g>5<5<;6=44i3d`>5<5<5<>o2=3:17d7m:188m45c2900e<=j:188m45a2900e<:?:188m7`d2900e?hk:188k7`42900c<=l:188yg52l3:1h7>50z&1b=<5lo1C?=h4H3d:?l352900e8=50;9j11<722c>97>5;h;a>5<5<5<5<5<j7>5d;294~"5n109hk5G31d8L7`>3`?96=44i4194?=n==0;66g:5;29?l?e2900e<=k:188m45b2900e<=i:188m4272900e?hl:188m7`c2900c?h<:188k45d2900qo=90;29`?6=8r.9j54=dg9K75`<@;l27d;=:188m05=831b994?::k61?6=3`3i6=44i01g>5<5<;6=44i3d`>5<5<5<>o>j3:17b=9?;0D>>i;I0e=>o?03:17d7=:188m<>=831b5o4?::m1`a<722wi9im50;794?6|,;l36<8>;I13b>N5n01b454?::k:6?6=3`336=44i8`94?=h:mn1<75rb4fg>5<2290;w)N48o1C>k74i9:94?=n1;0;66g68;29?l?e2900c?jk:188yg3cm3:197>50z&1b=<6>81C?=h4H3d:?l>?2900e4<50;9j==<722c2n7>5;n0g`?6=3th>hk4?:483>5}#:o21=;?4H22e?M4a12c347>5;h;1>5<>i5lm0;66sm5d294?3=83:p(?h7:042?M57n2B9j45f8983>>o>:3:17d77:188mij50;9~f0c6290>6=4?{%0e=831b5?4?::k:5<7>55;294~"5n10::<5G31d8L7`>3`236=44i8094?=n110;66g6b;29?j4cl3:17pl:a783>6<729q/>k651e28L66a3A8m56*>8480f>o6?00;66g>7`83>>i5l>0;66sm58g94?2=83:p(?h7:0f;?M57n2B9j45f9483>>of93:17d6<729q/>k6531g8L66a3A8m56g65;29?l7dk3:17b0;6>4?:1y'6c>=9m:0D>>i;I0e=>"60<0?j6g>7883>>o6?h0;66a=d683>>{e=0l1<7:50;2x 7`?28n37E=?f:J1b<=n1<0;66gn1;29?l4a83:17b4?:1y'6c>=;9o0D>>i;I0e=>o>=3:17d?lc;29?j4c?3:17pl:a983>6<729q/>k651e28L66a3A8m56*>8487b>o6?00;66g>7`83>>i5l>0;66sm5`294?2=83:p(?h7:0f;?M57n2B9j45f9483>>of93:17d6<729q/>k6531g8L66a3A8m56g65;29?l7dk3:17b4?:1y'6c>=9m:0D>>i;I0e=>"60<0?j6g>7883>>o6?h0;66a=d683>>{e=h;1<7:50;2x 7`?28n37E=?f:J1b<=n1<0;66gn1;29?l4a83:17b4?:1y'6c>=;9o0D>>i;I0e=>o>=3:17d?lc;29?j4c?3:17pl:a`83>6<729q/>k651e28L66a3A8m56*>8487b>o6?00;66g>7`83>>i5l>0;66sm5`094?2=83:p(?h7:0f;?M57n2B9j45f9483>>of93:17d6<729q/>k6531g8L66a3A8m56g65;29?l7dk3:17b4?:1y'6c>=9m:0D>>i;I0e=>"60<0?j6g>7883>>o6?h0;66a=d683>>{e=h91<7:50;2x 7`?28n37E=?f:J1b<=n1<0;66gn1;29?l4a83:17b4?:1y'6c>=;9o0D>>i;I0e=>o>=3:17d?lc;29?j4c?3:17pl:ab83>6<729q/>k651e28L66a3A8m56*>8487b>o6?00;66g>7`83>>i5l>0;66sm5`694?2=83:p(?h7:0f;?M57n2B9j45f9483>>of93:17d6<729q/>k6531g8L66a3A8m56g65;29?l7dk3:17b4?:1y'6c>=9m:0D>>i;I0e=>"60<0?j6g>7883>>o6?h0;66a=d683>>{e=h?1<7:50;2x 7`?28n37E=?f:J1b<=n1<0;66gn1;29?l4a83:17b4?:1y'6c>=;9o0D>>i;I0e=>o>=3:17d?lc;29?j4c?3:17pl:ad83>6<729q/>k651e28L66a3A8m56*>8487b>o6?00;66g>7`83>>i5l>0;66sm5c594?5=83:p(?h7:22f?M57n2B9j45f9483>>o6kj0;66a=d683>>{e9l81<7:50;2x 7`?28n27E=?f:J1b<=n9>31<75f16c94?=n:o:1<75`2e594?=zj8l96=4;:183!4a03;o>6F<0g9K6c?<,82>6<:<;h34=?6=3`;5;h34f?6=3f8o;7>5;|`2ad<72=0;6=u+2g:95a4<@::m7EN5n01b=:750;9j52g=831b>k>50;9l6a1=831vn:187>5<7s-8m47?k2:J04c=O:o30(<6::060?l7013:17d?8a;29?l70j3:17b=9m80D>>i;I0e=>"60<03>6g>7883>>o6?h0;66g>7c83>>i5l>0;66sm1d294?2=83:p(?h7:0f:?M57n2B9j45f16;94?=n9>k1<75f2g294?=h:m=1<75rb0d3>5<3290;w)N48o1C>k74$0:6>4243`;<57>5;h34e?6=3`;5;n0g3?6=3th:i54?:583>5}#:o21=i<4H22e?M4a12.:48472:k23<<722c:;l4?::k23g<722e9h:4?::a5a`=83>1<7>t$3d;>4b>3A9;j6F=f89j52?=831b=:o50;9j6c6=831d>i950;9~f4ca290?6=4?{%0e228>87d?89;29?l70i3:17d?8b;29?j4c?3:17pl>e683>1<729q/>k651e08L66a3A8m56*>848;6>o6?00;66g>7`83>>o6?k0;66a=d683>>{e9mo1<7:50;2x 7`?28n27E=?f:J1b<=n9>31<75f16c94?=n:o:1<75`2e594?=zj8on6=4;:183!4a03;o>6F<0g9K6c?<,82>6<:<;h34=?6=3`;5;h34f?6=3f8o;7>5;|`2a3<72=0;6=u+2g:95a4<@::m7EN5n01b=:750;9j52g=831b>k>50;9l6a1=831vn5<7s-8m47?k2:J04c=O:o30(<6::060?l7013:17d?8a;29?l70j3:17b=9m80D>>i;I0e=>"60<03>6g>7883>>o6?h0;66g>7c83>>i5l>0;66sm1ea94?2=83:p(?h7:0f:?M57n2B9j45f16;94?=n9>k1<75f2g294?=h:m=1<75rb0g`>5<3290;w)N48o1C>k74$0:6>4243`;<57>5;h34e?6=3`;5;n0g3?6=3th:i94?:583>5}#:o21=i<4H22e?M4a12.:48472:k23<<722c:;l4?::k23g<722e9h:4?::a5ad=83>1<7>t$3d;>4b>3A9;j6F=f89j52?=831b=:o50;9j6c6=831d>i950;9~f4ce290?6=4?{%0e228>87d?89;29?l70i3:17d?8b;29?j4c?3:17pl>e283>1<729q/>k651e08L66a3A8m56*>848;6>o6?00;66g>7`83>>o6?k0;66a=d683>>{e31<75f16c94?=n:o:1<75`2e594?=zj=o36=4<:183!4a03;o<6F<0g9K6c?<,82>6<:>;h34=?6=3`;5;n0g3?6=3th?ih4?:583>5}#:o21=io4H22e?M4a12c:;44?::k23d<722c9j=4?::m1`2<722wi8k?50;694?6|,;l36N5n01b=:750;9j52g=831b>k>50;9l6a1=831vn9h;:186>5<7s-8m47?k5:J04c=O:o30(<6::04:?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl;f283>0<729q/>k651e78L66a3A8m56*>84822<=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb5ge>5<3290;w)N48o1C>k74i05:>5<5<t$3d;>4b23A9;j6F=f89'5=3=9?30e<96:188m41f2900e<9m:188m41d2900c?j8:188yg34m3:1?7>50z&1b=<48l1C?=h4H3d:?l?22900e50z&1b=<6l11C?=h4H3d:?l?22900el?50;9j6c6=831d>i950;9~f02?29086=4?{%0e5<7s-8m47?k8:J04c=O:o30e4;50;9je4<722c9j=4?::m1`2<722wi99950;194?6|,;l36>>j;I13b>N5n01b584?::k2gf<722e9h:4?::a16>=83>1<7>t$3d;>4b?3A9;j6F=f89j=0<722cj=7>5;h0e4?6=3f8o;7>5;|`603<72:0;6=u+2g:975c<@::m7E5;n0g3?6=3th>?;4?:583>5}#:o21=i64H22e?M4a12c297>5;hc2>5<5<53;294~"5n1083`3>6=44i0a`>5<5<5<4290;w)N48o1C>k74i8794?=n9ji1<75`2e594?=zj<996=4;:183!4a03;o46F<0g9K6c?>o5n90;66a=d683>>{e==91<7=50;2x 7`?2::n7E=?f:J1b<=n1<0;66g>cb83>>i5l>0;66sm52294?2=83:p(?h7:0f;?M57n2B9j45f9483>>of93:17d6<729q/>k6531g8L66a3A8m56g65;29?l7dk3:17b=9m20D>>i;I0e=>o>=3:17do>:188m7`72900c?j8:188yg3393:1?7>50z&1b=<48l1C?=h4H3d:?l?22900ed99K75`<@;l27d7::188md7=831b>k>50;9l6a1=831vn8:?:180>5<7s-8m47=?e:J04c=O:o30e4;50;9j5fe=831d>i950;9~f04f290?6=4?{%0e1<7>t$3d;>4b?3A9;j6F=f89j=0<722cj=7>5;h0e4?6=3f8o;7>5;|`6>{e=1o1<7;50;2x 7`?28<:7E=?f:J1b<=n010;66g62;29?l??2900e4l50;9l6ab=831vn878:186>5<7s-8m47?91:J04c=O:o30e5650;9j=7<722c247>5;h;a>5<5<>o>j3:17b=9?;0D>>i;I0e=>o?03:17d7=:188m<>=831b5o4?::m1`a<722wi94:50;794?6|,;l36<8>;I13b>N5n01b454?::k:6?6=3`336=44i8`94?=h:mn1<75rb4;0>5<2290;w)N48o1C>k74i9:94?=n1;0;66g68;29?l?e2900c?jk:188yg3>:3:197>50z&1b=<6>81C?=h4H3d:?l>?2900e4<50;9j==<722c2n7>5;n0g`?6=3th>5<4?:483>5}#:o21=;?4H22e?M4a12c347>5;h;1>5<>i5lm0;66sm58294?3=83:p(?h7:042?M57n2B9j45f8983>>o>:3:17d77:188mij50;9~f0>c290>6=4?{%0e=831b5?4?::k:5<55;294~"5n10::<5G31d8L7`>3`236=44i8094?=n110;66g6b;29?j4cl3:17pl:5883>1<729q/>k651708L66a3A8m56g78;29?l?52900e4l50;9l6ab=831vn8;7:187>5<7s-8m47?92:J04c=O:o30e5650;9j=7<722c2n7>5;n0g`?6=3th>:<4?:583>5}#:o21=;<4H22e?M4a12c347>5;h;1>5<6F<0g9K6c?>o>j3:17b=9?80D>>i;I0e=>o?03:17d7=:188mij50;9~f03b290?6=4?{%0e=831b5?4?::k:f?6=3f8oh7>5;|`61a<72=0;6=u+2g:9534<@::m7E5<3290;w)N48o1C>k74i9:94?=n1;0;66g6b;29?j4cl3:17pl:5c83>1<729q/>k651708L66a3A8m56g78;29?l?52900e4l50;9l6ab=831vn8;n:187>5<7s-8m47?92:J04c=O:o30e5650;9j=7<722c2n7>5;n0g`?6=3th>9:4?:583>5}#:o21=;<4H22e?M4a12c347>5;h;1>5<6F<0g9K6c?>o>j3:17b4?:1y'6c>=9>i;I0e=>o?03:17d7m:188k7bc2900qo::2;297?6=8r.9j54>5g9K75`<@;l27d67:188mij50;9~f13629086=4?{%0e=831b5o4?::m1`a<722wi88>50;194?6|,;l36<;i;I13b>N5n01b454?::k:f?6=3f8oh7>5;|`70c<72:0;6=u+2g:950`<@::m7E5<?n7>53;294~"5n10:9k5G31d8L7`>3`236=44i8`94?=h:mn1<75rb56g>5<4290;w)N48o1C>k74i9:94?=n1k0;66a=de83>>{e<=31<7=50;2x 7`?28?m7E=?f:J1b<=n010;66g6b;29?j4cl3:17pl;4983>6<729q/>k6514d8L66a3A8m56g78;29?l?e2900c?jk:188yg23?3:1?7>50z&1b=<6=o1C?=h4H3d:?l>?2900e4l50;9l6ab=831vn9:9:180>5<7s-8m47?:f:J04c=O:o30e5650;9j=g<722e9hi4?::a01c=8391<7>t$3d;>43a3A9;j6F=f89j<=<722c2n7>5;n0g`?6=3th?8l4?:283>5}#:o21=8h4H22e?M4a12c347>5;h;a>5<5<>i5lm0;66sm47094?5=83:p(?h7:07e?M57n2B9j45f8983>>o>j3:17b80;6>4?:1y'6c>=9>i;I0e=>o?03:17d7m:188k7bc2900qo::f;297?6=8r.9j54>5g9K75`<@;l27d67:188mij50;9~f13b29086=4?{%0e=831b5o4?::m1`a<722wi?;m50;694?6|,;l36N5n01b584?::kb5?6=3`8m<7>5;n0g3?6=3th8:i4?:583>5}#:o21=i64H22e?M4a12c297>5;hc2>5<5<53;294~"5n1083`3>6=44i0a`>5<5<5<4290;w)N48o1C>k74i8794?=n9ji1<75`2e594?=zj:>o5n90;66a=d683>>{e;1:1<7=50;2x 7`?2::n7E=?f:J1b<=n1<0;66g>cb83>>i5l>0;66sm36294?2=83:p(?h7:0f;?M57n2B9j45f9483>>of93:17d6<729q/>k6531g8L66a3A8m56g65;29?l7dk3:17b=9m20D>>i;I0e=>o>=3:17do>:188m7`72900c?j8:188yg5?:3:1?7>50z&1b=<48l1C?=h4H3d:?l?22900ed99K75`<@;l27d7::188md7=831b>k>50;9l6a1=831vn>6<:180>5<7s-8m47=?e:J04c=O:o30e4;50;9j5fe=831d>i950;9~f614290?6=4?{%0et$3d;>66b3A9;j6F=f89j=0<722c:on4?::m1`2<722wi?::50;694?6|,;l36N5n01b584?::kb5?6=3`8m<7>5;n0g3?6=3th8484?:283>5}#:o21?=k4H22e?M4a12c297>5;h3`g?6=3f8o;7>5;|`0<3<72:0;6=u+2g:975c<@::m7E5;n0g3?6=3th?=o4?:483>5}#:o21=;?4H22e?M4a12c347>5;h;1>5<>i5lm0;66sm3`694?3=83:p(?h7:042?M57n2B9j45f8983>>o>:3:17d77:188mij50;9~f6g4290>6=4?{%0e=831b5?4?::k:5<7>55;294~"5n10::<5G31d8L7`>3`236=44i8094?=n110;66g6b;29?j4cl3:17pl0<729q/>k651738L66a3A8m56g78;29?l?52900e4650;9j=g<722e9hi4?::a7d6=83?1<7>t$3d;>4063A9;j6F=f89j<=<722c2>7>5;h;;>5<>o>03:17d7m:188k7bc2900qo=6e;291?6=8r.9j54>609K75`<@;l27d67:188m<4=831b554?::k:f?6=3f8oh7>5;|`0=a<72<0;6=u+2g:9537<@::m7E>{e<8k1<7;50;2x 7`?28<:7E=?f:J1b<=n010;66g62;29?l??2900e4l50;9l6ab=831vn;ll:180>5<7s-8m47?k0:J04c=O:o30(<6::548m41>2900e<9n:188k7b02900qo:id;297?6=8r.9j54>d19K75`<@;l27)?75;0f?l7013:17d?8a;29?j4c?3:17pl;dd83>6<729q/>k651e28L66a3A8m56*>8481a>o6?00;66g>7`83>>i5l>0;66sm4ef94?5=83:p(?h7:0f3?M57n2B9j45+19796`=n9>31<75f16c94?=h:m=1<75rb5`g>5<4290;w)N48o1C>k74$0:6>105<5;h34e?6=3f8o;7>5;|`02g<72:0;6=u+2g:95a6<@::m7E1<7>t$3d;>4b53A9;j6F=f89'5=3=9<<0e<96:188m41f2900e<9m:188k7b02900qo=ne;290?6=8r.9j54>d39K75`<@;l27)?75;30?l7013:17d?8a;29?l70j3:17b=9m?0D>>i;I0e=>"60<0:56g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e>0n1<7;50;2x 7`?28n>7E=?f:J1b<=#91?1445f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj=l36=4::183!4a03;o96F<0g9K6c?<,82>6964i05:>5<5<5<ii7>55;294~"5n10:h85G31d8L7`>3-;397:7;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th?><4?:483>5}#:o21=i;4H22e?M4a12.:484>7:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi8=j50;794?6|,;l36N5n01/=5;5149j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn>om:186>5<7s-8m47?k5:J04c=O:o30(<6::`9j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn>:7:186>5<7s-8m47?k5:J04c=O:o30(<6::058m41>2900e<9n:188m41e2900e<9l:188k7b02900qo:mc;291?6=8r.9j54>d49K75`<@;l27)?75;;g?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl0<729q/>k651e78L66a3A8m56*>8484?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl;2283>0<729q/>k651e78L66a3A8m56*>84826>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm42094?3=83:p(?h7:0f6?M57n2B9j45+197900=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb5d4>5<2290;w)N48o1C>k74$0:6>7e5<5<5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`7b0<72<0;6=u+2g:95a3<@::m7Et$3d;>4b23A9;j6F=f89'5=3=<;1b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f1`d290?6=4?{%0e22;:0e<96:188m41f2900e<9m:188k7b02900qo:j2;291?6=8r.9j54>d49K75`<@;l27)?75;f8m41>2900e<9n:188m41e2900e<9l:188k7b02900qo:ib;291?6=8r.9j54>d49K75`<@;l27)?75;:5?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl;f883>1<729q/>k651e08L66a3A8m56*>848e?l7013:17d?8a;29?l70j3:17b=9m?0D>>i;I0e=>"60<0:8;5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj=nj6=4;:183!4a03;o>6F<0g9K6c?<,82>6<::;h34=?6=3`;5;h34f?6=3f8o;7>5;|`7`=<72<0;6=u+2g:95a3<@::m7Ei950;9~f066290>6=4?{%0e22<:0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg2cn3:197>50z&1b=<6l<1C?=h4H3d:?!7?=3;?i6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e7E=?f:J1b<=#91?1o6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e7E=?f:J1b<=#91?1=l5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj=i<6=4::183!4a03;o96F<0g9K6c?<,82>655f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj=i36=4::183!4a03;o96F<0g9K6c?<,82>6<:7;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th>5}#:o21=i>4H22e?M4a12.:484;f:k23<<722c:;l4?::m1`2<722wi9N5n01/=5;5419j52?=831b=:o50;9j52d=831d>i950;9~f06d290?6=4?{%0e22o1b=:750;9j52g=831b=:l50;9l6a1=831vn;>n:180>5<7s-8m47?k0:J04c=O:o30(<6::548m41>2900e<9n:188k7b02900qo:<5;291?6=8r.9j54>d49K75`<@;l27)?75;68m41>2900e<9n:188m41e2900e<9l:188k7b02900qo8<0;290?6=8r.9j54>d39K75`<@;l27)?75;377>o6?00;66g>7`83>>o6?k0;66a=d683>>{e>;l1<7:50;2x 7`?28n97E=?f:J1b<=#91?1=9=4i05:>5<5<N5n01/=5;5839j52?=831b=:o50;9j52d=831d>i950;9~f34d290?6=4?{%0e22180e<96:188m41f2900e<9m:188k7b02900qo8=b;290?6=8r.9j54>d39K75`<@;l27)?75;:1?l7013:17d?8a;29?l70j3:17b=9m80D>>i;I0e=>"60<03>6g>7883>>o6?h0;66g>7c83>>i5l>0;66sm62394?2=83:p(?h7:0f1?M57n2B9j45+1979<7=n9>31<75f16c94?=n9>h1<75`2e594?=zj:?36=4<:183!4a03;o<6F<0g9K6c?<,82>6984i05:>5<5<55;294~"5n10:h85G31d8L7`>3-;397?8;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th>>;4?:583>5}#:o21=i<4H22e?M4a12.:484=f:k23<<722c:;l4?::k23g<722e9h:4?::a2<0=83?1<7>t$3d;>4b23A9;j6F=f89'5=3=<11b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f3?2290>6=4?{%0e228=87d?89;29?l70i3:17d?8b;29?l70k3:17bl0;684?:1y'6c>=9m?0D>>i;I0e=>"60<02?6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e=?n1<7:50;2x 7`?28n97E=?f:J1b<=#91?1=9=4i05:>5<5<5;h34e?6=3f8o;7>5;|`6=f<72<0;6=u+2g:95a3<@::m7E>1b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f10?290>6=4?{%0e22<20e<96:188m41f2900e<9m:188m41d2900c?j8:188yg21j3:187>50z&1b=<6l;1C?=h4H3d:?!7?=3><7d?89;29?l70i3:17d?8b;29?j4c?3:17pl;6`83>0<729q/>k651e78L66a3A8m56*>848b4>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm42a94?3=83:p(?h7:0f6?M57n2B9j45+197961=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb77g>5<3290;w)N48o1C>k74$0:6>5<5<n7>54;294~"5n10:h?5G31d8L7`>3-;3977j;h34=?6=3`;5;h34f?6=3f8o;7>5;|`51<<72=0;6=u+2g:95a4<@::m7Em2c:;44?::k23d<722c:;o4?::m1`2<722wi:8950;694?6|,;l36N5n01/=5;59d9j52?=831b=:o50;9j52d=831d>i950;9~f332290?6=4?{%0e220o0e<96:188m41f2900e<9m:188k7b02900qo8:3;290?6=8r.9j54>d39K75`<@;l27)?75;;f?l7013:17d?8a;29?l70j3:17b=9m80D>>i;I0e=>"60<02i6g>7883>>o6?h0;66g>7c83>>i5l>0;66sm65d94?2=83:p(?h7:0f1?M57n2B9j45+1979=`=n9>31<75f16c94?=n9>h1<75`2e594?=zj?;;6=4;:183!4a03;o>6F<0g9K6c?<,82>6<:<;h34=?6=3`;5;h34f?6=3f8o;7>5;|`552<72=0;6=u+2g:95a4<@::m7E5<7s-8m47?k5:J04c=O:o30(<6::868m41>2900e<9n:188m41e2900e<9l:188k7b02900qo8>3;290?6=8r.9j54>d39K75`<@;l27)?75;377>o6?00;66g>7`83>>o6?k0;66a=d683>>{e;k=1<7;50;2x 7`?28n>7E=?f:J1b<=#91?1=;l4i05:>5<5<5<55;294~"5n10:h85G31d8L7`>3-;397?96:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi?n;50;794?6|,;l36N5n01/=5;514`8m41>2900e<9n:188m41e2900e<9l:188k7b02900qo=la;291?6=8r.9j54>d49K75`<@;l27)?75;352>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm33794?2=83:p(?h7:0f1?M57n2B9j45+1979<7=n9>31<75f16c94?=n9>h1<75`2e594?=zj:n86=4::183!4a03;o96F<0g9K6c?<,82>6<8m;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th8h54?:483>5}#:o21=i;4H22e?M4a12.:484>679j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn><<:187>5<7s-8m47?k2:J04c=O:o30(<6::908m41>2900e<9n:188m41e2900c?j8:188yg5b93:197>50z&1b=<6l<1C?=h4H3d:?!7?=3;=i6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e;l<1<7;50;2x 7`?28n>7E=?f:J1b<=#91?1=;84i05:>5<5<5<54;294~"5n10:h?5G31d8L7`>3-;3976=;h34=?6=3`;5;h34f?6=3f8o;7>5;|`0ac<72<0;6=u+2g:95a3<@::m7Ei950;9~f6`3290>6=4?{%0e228<=7d?89;29?l70i3:17d?8b;29?l70k3:17b=9m80D>>i;I0e=>"60<03>6g>7883>>o6?h0;66g>7c83>>i5l>0;66sm3gf94?3=83:p(?h7:0f6?M57n2B9j45+197953d5<5<2c:;44?::k23d<722c:;o4?::k23f<722e9h:4?::a74b=83>1<7>t$3d;>4b53A9;j6F=f89'5=3=0;1b=:750;9j52g=831b=:l50;9l6a1=831vn9>j:186>5<7s-8m47?k5:J04c=O:o30(<6::06:?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl;0c83>1<729q/>k651e08L66a3A8m56*>848:a>o6?00;66g>7`83>>o6?k0;66a=d683>>{e<9i1<7:50;2x 7`?28n97E=?f:J1b<=#91?1=>5f16;94?=n9>k1<75f16`94?=h:m=1<75rb52e>5<3290;w)N48o1C>k74$0:6>455<5<:>7>55;294~"5n10:h85G31d8L7`>3-;397?;b:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi8=o50;794?6|,;l36N5n01/=5;51748m41>2900e<9n:188m41e2900e<9l:188k7b02900qo=>b;290?6=8r.9j54>d39K75`<@;l27)?75;:1?l7013:17d?8a;29?l70j3:17b=9m80D>>i;I0e=>"60<03>6g>7883>>o6?h0;66g>7c83>>i5l>0;66sm30594?2=83:p(?h7:0f1?M57n2B9j45+1979<7=n9>31<75f16c94?=n9>h1<75`2e594?=zj?8;6=4::183!4a03;o96F<0g9K6c?<,82>64:4i05:>5<5<5<54;294~"5n10:h?5G31d8L7`>3-;397?;3:k23<<722c:;l4?::k23g<722e9h:4?::a03`=83?1<7>t$3d;>4b23A9;j6F=f89'5=3==o1b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f114290>6=4?{%0e228?j7d?89;29?l70i3:17d?8b;29?l70k3:17b=9m?0D>>i;I0e=>"60<0?7d?89;29?l70i3:17d?8b;29?l70k3:17b=9m80D>>i;I0e=>"60<027d?89;29?l70i3:17d?8b;29?j4c?3:17pl;2483>0<729q/>k651e78L66a3A8m56*>848214=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb7;a>5<3290;w)N48o1C>k74i9:94?=n1k0;66g=dd83>>i5lm0;66sm68c94?2=83:p(?h7:047?M57n2B9j45f8983>>o>j3:17d1<729q/>k651768L66a3A8m56g78;29?l?e2900e?jj:188k7bc2900qo;=9;296?6=8r.9j54>cg9K75`<@;l27)?75;01?l7013:17b=9jl0D>>i;I0e=>"60<09>6g>7883>>i5l>0;66sm52;94?4=83:p(?h7:0ae?M57n2B9j45+197967=n9>31<75`2e594?=zj<9<6=4=:183!4a03;hj6F<0g9K6c?<,82>6?<4i05:>5<5;n0g3?6=3th>?>4?:383>5}#:o21=nh4H22e?M4a12.:484=2:k23<<722e9h:4?::a167=8381<7>t$3d;>4ea3A9;j6F=f89'5=3=:;1b=:750;9l6a1=831vn85<7s-8m47?lf:J04c=O:o30(<6::308m41>2900c?j8:188yg35l3:1>7>50z&1b=<6ko1C?=h4H3d:?!7?=3897d?89;29?j4c?3:17pl:2c83>7<729q/>k651bd8L66a3A8m56*>84816>o6?00;66a=d683>>{e=:l1<7<50;2x 7`?28im7E=?f:J1b<=#91?1>?5f16;94?=h:m=1<75rb544>5<2290;w)N48o1C>k74$0:6>1?5<5<5<>i5lm0;66sm44a94?5=83:p(?h7:07e?M57n2B9j45f8983>>o>j3:17b4?:1y'6c>=9>i;I0e=>o?03:17d7m:188k7bc2900qo:6a;291?6=8r.9j54>d49K75`<@;l27)?75;346>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm48`94?3=83:p(?h7:0f6?M57n2B9j45+19795235<5<5<>i5lm0;66sm48394?2=83:p(?h7:040?M57n2B9j45f8983>>o>j3:17d1<729q/>k651728L66a3A8m56g78;29?l??2900e4l50;9l6ab=831vn96<:187>5<7s-8m47?90:J04c=O:o30e5650;9j==<722c2n7>5;n0g`?6=3th?4<4?:583>5}#:o21=;>4H22e?M4a12c347>5;h;;>5<>o>j3:17b=9?90D>>i;I0e=>o?03:17d7m:188m7bd2900c?jk:188yg2fm3:187>50z&1b=<6>91C?=h4H3d:?l>?2900e4650;9j=g<722e9hi4?::a0de=83>1<7>t$3d;>4073A9;j6F=f89j<=<722c247>5;h;a>5<5<>i5lm0;66sm4`:94?2=83:p(?h7:043?M57n2B9j45f8983>>o>03:17d7m:188k7bc2900qo::d;291?6=8r.9j54>d49K75`<@;l27)?75;35<>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm44`94?3=83:p(?h7:0f6?M57n2B9j45+197953g5<5<5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`731<72<0;6=u+2g:95a3<@::m7Et$3d;>4b23A9;j6F=f89'5=3=9>?0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg2583:197>50z&1b=<6l<1C?=h4H3d:?!7?=33m7d?89;29?l70i3:17d?8b;29?l70k3:17b=9m?0D>>i;I0e=>"60<03<6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e;>=1<7;50;2x 7`?28n>7E=?f:J1b<=#91?14=5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj:=36=4::183!4a03;o96F<0g9K6c?<,82>65>4i05:>5<5<5<55;294~"5n10:h85G31d8L7`>3-;3976?;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th8;l4?:483>5}#:o21=i;4H22e?M4a12.:48470:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi?:l50;794?6|,;l36N5n01/=5;5819j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn>9l:186>5<7s-8m47?k5:J04c=O:o30(<6::928m41>2900e<9n:188m41e2900e<9l:188k7b02900qo=8d;291?6=8r.9j54>d49K75`<@;l27)?75;:3?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl;9g83>0<729q/>k651e78L66a3A8m56*>84804>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm4`094?3=83:p(?h7:0f6?M57n2B9j45+19791<=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb5c0>5<2290;w)N48o1C>k74$0:6>=55<5<t$3d;>4b23A9;j6F=f89'5=3=9=80e<96:188m41f2900e<9m:188m41d2900c?j8:188yg2?m3:197>50z&1b=<6l<1C?=h4H3d:?!7?=3;?>6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e<1<1<7;50;2x 7`?28n>7E=?f:J1b<=#91?14>5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj=2?6=4::183!4a03;o96F<0g9K6c?<,82>65=4i05:>5<5<5<3>7>55;294~"5n10:h85G31d8L7`>3-;3976<;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th?4=4?:483>5}#:o21=i;4H22e?M4a12.:48473:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi8lh50;794?6|,;l36N5n01/=5;5829j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn9ok:186>5<7s-8m47?k5:J04c=O:o30(<6::918m41>2900e<9n:188m41e2900e<9l:188k7b02900qo:nb;291?6=8r.9j54>d49K75`<@;l27)?75;:0?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl;b283>0<729q/>k651e78L66a3A8m56*>8486g>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm4`;94?3=83:p(?h7:0f6?M57n2B9j45+1979<6=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb2c5>5<2290;w)N48o1C>k74$0:6>4133`;<57>5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`72`<72<0;6=u+2g:95a3<@::m7Ei950;9~f6gc290>6=4?{%0e223:197>50z&1b=<6l<1C?=h4H3d:?!7?=3;>?6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e<;k1<7;50;2x 7`?28n>7E=?f:J1b<=#91?15n5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj=8<6=4::183!4a03;o96F<0g9K6c?<,82>6964i05:>5<5<5<:i7>54;294~"5n10:h?5G31d8L7`>3-;397?;a:k23<<722c:;l4?::k23g<722e9h:4?::a723=83?1<7>t$3d;>4b23A9;j6F=f89'5=3==81b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f1c3290>6=4?{%0e228i0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg2d=3:197>50z&1b=<6l<1C?=h4H3d:?!7?=3=0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg31k3:197>50z&1b=<6l<1C?=h4H3d:?!7?=3387d?89;29?l70i3:17d?8b;29?l70k3:17bk0;694?:1y'6c>=9m80D>>i;I0e=>"60<0:8>5f16;94?=n9>k1<75f16`94?=h:m=1<75rb4:3>5<2290;w)N48o1C>k74$0:6><55<5<N5n01/=5;5929j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn89k:187>5<7s-8m47?k2:J04c=O:o30(<6::060?l7013:17d?8a;29?l70j3:17b=9m?0D>>i;I0e=>"60<02?6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e=>h1<7:50;2x 7`?28n97E=?f:J1b<=#91?1=9=4i05:>5<5<5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`63<<72=0;6=u+2g:95a4<@::m7E5<7s-8m47?k5:J04c=O:o30(<6::818m41>2900e<9n:188m41e2900e<9l:188k7b02900qo;87;290?6=8r.9j54>d39K75`<@;l27)?75;377>o6?00;66g>7`83>>o6?k0;66a=d683>>{e=><1<7;50;2x 7`?28n>7E=?f:J1b<=#91?15>5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj<=>6=4;:183!4a03;o>6F<0g9K6c?<,82>6<:<;h34=?6=3`;5;h34f?6=3f8o;7>5;|`631<72<0;6=u+2g:95a3<@::m7E;2c:;44?::k23d<722c:;o4?::k23f<722e9h:4?::a125=83>1<7>t$3d;>4b53A9;j6F=f89'5=3=9=90e<96:188m41f2900e<9m:188k7b02900qo;82;291?6=8r.9j54>d49K75`<@;l27)?75;;0?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl:7083>1<729q/>k651e08L66a3A8m56*>848206=n9>31<75f16c94?=n9>h1<75`2e594?=zj<6F<0g9K6c?<,82>6<:<;h34=?6=3`;5;h34f?6=3f8o;7>5;|`0fd<72<0;6=u+2g:95a3<@::m7Ek2c:;44?::k23d<722c:;o4?::k23f<722e9h:4?::a7g0=83?1<7>t$3d;>4b23A9;j6F=f89'5=3=1j1b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f6e?290>6=4?{%0e220i0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg5d<3:197>50z&1b=<6l<1C?=h4H3d:?!7?=33h7d?89;29?l70i3:17d?8b;29?l70k3:17b=9m?0D>>i;I0e=>"60<02o6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e;m81<7;50;2x 7`?28n>7E=?f:J1b<=#91?15n5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj:o?6=4::183!4a03;o96F<0g9K6c?<,82>64m4i05:>5<5<5<55;294~"5n10:h85G31d8L7`>3-;3977l;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th8j?4?:483>5}#:o21=i;4H22e?M4a12.:4846c:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi?hk50;794?6|,;l36N5n01/=5;59b9j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn9>?:186>5<7s-8m47?k5:J04c=O:o30(<6::8a8m41>2900e<9n:188m41e2900e<9l:188k7b02900qo=ic;291?6=8r.9j54>d49K75`<@;l27)?75;;`?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl;8683>0<729q/>k651e78L66a3A8m56*>8481`>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm49:94?3=83:p(?h7:0f6?M57n2B9j45+19795015<5<e3`;<57>5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`623<72:0;6=u+2g:95a6<@::m7Ej2c:;44?::k23d<722e9h:4?::a7<7=83?1<7>t$3d;>4b23A9;j6F=f89'5=3=9?i0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg0><3:197>50z&1b=<6l<1C?=h4H3d:?!7?=3;;7d?89;29?l70i3:17d?8b;29?l70k3:17b=9m?0D>>i;I0e=>"60<09?6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e=?=1<7;50;2x 7`?28n>7E=?f:J1b<=#91?15<5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj6<9?;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th?=k4?:483>5}#:o21=i;4H22e?M4a12.:484>539j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn9=?:186>5<7s-8m47?k5:J04c=O:o30(<6::071?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl0<729q/>k651e78L66a3A8m56*>84820a=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb2a5>5<2290;w)N48o1C>k74$0:6>42c3`;<57>5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`0`1<72<0;6=u+2g:95a3<@::m7Ei950;9~f6c5290>6=4?{%0e228>o7d?89;29?l70i3:17d?8b;29?l70k3:17b=9m?0D>>i;I0e=>"60<0:8i5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj:ln6=4::183!4a03;o96F<0g9K6c?<,82>6<:k;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th>=h4?:483>5}#:o21=i;4H22e?M4a12.:484>9:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi9N5n01/=5;515:8m41>2900e<9n:188m41e2900e<9l:188k7b02900qo:k7;291?6=8r.9j54>d49K75`<@;l27)?75;35=>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm4e494?3=83:p(?h7:0f6?M57n2B9j45+19792>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm34694?3=83:p(?h7:0f6?M57n2B9j45+197964=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb270>5<2290;w)N48o1C>k74$0:6>=e5<5<5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`646<72=0;6=u+2g:95a4<@::m7E5;h34e?6=3`;5;n0g3?6=3th?o>4?:483>5}#:o21=i;4H22e?M4a12.:484>459j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn9m;:187>5<7s-8m47?k2:J04c=O:o30(<6::046?l7013:17d?8a;29?l70j3:17b=9m?0D>>i;I0e=>"60<0:=6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e7E=?f:J1b<=#91?14<5f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj=o=6=4::183!4a03;o96F<0g9K6c?<,82>6>?4i05:>5<5<5<53;294~"5n10:h=5G31d8L7`>3-;3977m;h34=?6=3`;5;n0g3?6=3th8ml4?:483>5}#:o21=i;4H22e?M4a12.:484m;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th?i>4?:483>5}#:o21=i;4H22e?M4a12.:484>6g9j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn8?6:186>5<7s-8m47?k5:J04c=O:o30(<6::5:8m41>2900e<9n:188m41e2900e<9l:188k7b02900qo=64;297?6=8r.9j54>d19K75`<@;l27)?75;;a?l7013:17d?8a;29?j4c?3:17pl:9`83>0<729q/>k651e78L66a3A8m56*>848237=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb4;a>5<2290;w)N48o1C>k74$0:6>1>5<5<5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`650<72=0;6=u+2g:95a4<@::m7EN5n01/=5;5459j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn9mi:186>5<7s-8m47?k5:J04c=O:o30(<6::4c8m41>2900e<9n:188m41e2900e<9l:188k7b02900qo;=5;290?6=8r.9j54>d39K75`<@;l27)?75;30?l7013:17d?8a;29?l70j3:17b10;684?:1y'6c>=9m?0D>>i;I0e=>"60<0396g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e7E=?f:J1b<=#91?1=864i05:>5<5<5<h=7>54;294~"5n10:h?5G31d8L7`>3-;397?:f:k23<<722c:;l4?::k23g<722e9h:4?::a0g`=83?1<7>t$3d;>4b23A9;j6F=f89'5=3=k2c:;44?::k23d<722c:;o4?::k23f<722e9h:4?::a07>=83?1<7>t$3d;>4b23A9;j6F=f89'5=3=9?1b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f1b3290?6=4?{%0e22==0e<96:188m41f2900e<9m:188k7b02900qo:k5;291?6=8r.9j54>d49K75`<@;l27)?75;36=>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm4e194?3=83:p(?h7:0f6?M57n2B9j45+197976=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb5f`>5<3290;w)N48o1C>k74$0:6>c=n9>31<75f16c94?=n9>h1<75`2e594?=zj=h36=4::183!4a03;o96F<0g9K6c?<,82>6?=4i05:>5<5<5<n<7>55;294~"5n10:h85G31d8L7`>3-;397?:d:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi8n750;794?6|,;l36N5n01/=5;51758m41>2900e<9n:188m41e2900e<9l:188k7b02900qo:=9;291?6=8r.9j54>d49K75`<@;l27)?75;11?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl90e83>0<729q/>k651738L66a3A8m56*>8483?l>?2900e4<50;9j==<722c2n7>5;n0g`?6=3th==94?:583>5}#:o21=i<4H22e?M4a12.:484>429j52?=831b=:o50;9j52d=831d>i950;9~f37?290?6=4?{%0e228>87d?89;29?l70i3:17d?8b;29?j4c?3:17pl97b83>1<729q/>k651e;8L66a3A8m56g>7883>>o6?h0;66g=f183>>i5l>0;66sm66f94?3=83:p(?h7:0f6?M57n2B9j45+1979<1=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb75f>5<2290;w)N48o1C>k74$0:6>4333`;<57>5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`53<<72=0;6=u+2g:95a?<@::m7Et$3d;>4b23A9;j6F=f89'5=3=0=1b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f31e290>6=4?{%0e228??7d?89;29?l70i3:17d?8b;29?l70k3:17b=9m30D>>i;I0e=>o6?00;66g>7`83>>o5n90;66a=d683>>{e>>=1<7;50;2x 7`?28n>7E=?f:J1b<=#91?1495f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj?=36=4::183!4a03;o96F<0g9K6c?<,82>6<;;;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th=;>4?:583>5}#:o21=i74H22e?M4a12c:;44?::k23d<722c9j=4?::m1`2<722wi:::50;794?6|,;l36N5n01/=5;5859j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn;9::186>5<7s-8m47?k5:J04c=O:o30(<6::077?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl97183>1<729q/>k651e;8L66a3A8m56g>7883>>o6?h0;66g=f183>>i5l>0;66sm66394?3=83:p(?h7:0f6?M57n2B9j45+1979<1=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb751>5<2290;w)N48o1C>k74$0:6>4333`;<57>5;h34e?6=3`;5;h34g?6=3f8o;7>5;|`52a<72=0;6=u+2g:95a?<@::m7Et$3d;>4b23A9;j6F=f89'5=3=0=1b=:750;9j52g=831b=:l50;9j52e=831d>i950;9~f30a290>6=4?{%0e228??7d?89;29?l70i3:17d?8b;29?l70k3:17bh0;694?:1y'6c>=9m30D>>i;I0e=>o6?00;66g>7`83>>o5n90;66a=d683>>{e>?h1<7;50;2x 7`?28n>7E=?f:J1b<=#91?1495f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj?6<;;;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th=:<4?:583>5}#:o21=i74H22e?M4a12c:;44?::k23d<722c9j=4?::m1`2<722wi:;<50;794?6|,;l36N5n01/=5;5859j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn;8<:186>5<7s-8m47?k5:J04c=O:o30(<6::077?l7013:17d?8a;29?l70j3:17d?8c;29?j4c?3:17pl1<729q/>k651e;8L66a3A8m56g>7883>>o6?h0;66g=f183>>i5l>0;66sm3c294?3=83:p(?h7:0f6?M57n2B9j45+197963=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb2`2>5<2290;w)N48o1C>k74$0:6>015<5<5;h0e4?6=3f8o;7>5;|`664<72<0;6=u+2g:95a3<@::m7E1<7>t$3d;>4b53A9;j6F=f89'5=3=9d89K75`<@;l27d?89;29?l70i3:17d0<729q/>k651e78L66a3A8m56*>848;e>o6?00;66g>7`83>>o6?k0;66g>7b83>>i5l>0;66sm3`;94?3=83:p(?h7:0f6?M57n2B9j45+197966=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb41`>5<5290;w)N48o1C>k74i05;>5<5;|`54c<72;0;6=u+2g:95f><@::m7Et$3d;>4b23A9;j6F=f89'5=3=9?30e<96:188m41f2900e<9m:188m41d2900c?j8:188yg3783:1?7>50z&1b=<6l91C?=h4H3d:?!7?=33i7d?89;29?l70i3:17b=9m30D>>i;I0e=>o6?00;66g>7`83>>o5n90;66a=d683>>{e<:91<7;50;2x 7`?28n>7E=?f:J1b<=#91?1m6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e<:>1<7:50;2x 7`?28n27E=?f:J1b<=n9>31<75f16c94?=n:o:1<75`2e594?=zj<:>6=4::183!4a03;o96F<0g9K6c?<,82>6>m4i05:>5<5<5<54;294~"5n10:h45G31d8L7`>3`;<57>5;h34e?6=3`8m<7>5;n0g3?6=3th=>:4?:483>5}#:o21=i;4H22e?M4a12.:484>559j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn;<7:186>5<7s-8m47?k5:J04c=O:o30(<6::968m41>2900e<9n:188m41e2900e<9l:188k7b02900qo8=9;290?6=8r.9j54>d89K75`<@;l27d?89;29?l70i3:17d0<729q/>k651e78L66a3A8m56*>848211=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb701>5<2290;w)N48o1C>k74$0:6>=25<5<5;h0e4?6=3f8o;7>5;|`006<72<0;6=u+2g:95a3<@::m7Ei950;9~f623290>6=4?{%0e221>0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg53=3:187>50z&1b=<6l01C?=h4H3d:?l7013:17d?8a;29?l4a83:17b=9m?0D>>i;I0e=>"60<0:995f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj:>;6=4::183!4a03;o96F<0g9K6c?<,82>65:4i05:>5<5<5<54;294~"5n10:h45G31d8L7`>3`;<57>5;h34e?6=3`8m<7>5;n0g3?6=3th8?o4?:483>5}#:o21=i;4H22e?M4a12.:484>559j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn>=l:186>5<7s-8m47?k5:J04c=O:o30(<6::968m41>2900e<9n:188m41e2900e<9l:188k7b02900qo=d89K75`<@;l27d?89;29?l70i3:17d0<729q/>k651e78L66a3A8m56*>848211=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb706>5<2290;w)N48o1C>k74$0:6>=25<5<5;h0e4?6=3f8o;7>5;|`55g<72<0;6=u+2g:95a3<@::m7Ei950;9~f37d290>6=4?{%0e221>0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg06l3:187>50z&1b=<6l01C?=h4H3d:?l7013:17d?8a;29?l4a83:17b0;684?:1y'6c>=9m?0D>>i;I0e=>"60<0:995f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj:936=4::183!4a03;o96F<0g9K6c?<,82>65:4i05:>5<5<5<54;294~"5n10:h45G31d8L7`>3`;<57>5;h34e?6=3`8m<7>5;n0g3?6=3th8?>4?:483>5}#:o21=i;4H22e?M4a12.:484>559j52?=831b=:o50;9j52d=831b=:m50;9l6a1=831vn>=;:186>5<7s-8m47?k5:J04c=O:o30(<6::968m41>2900e<9n:188m41e2900e<9l:188k7b02900qo=<5;290?6=8r.9j54>d89K75`<@;l27d?89;29?l70i3:17d0<729q/>k651e78L66a3A8m56*>848211=n9>31<75f16c94?=n9>h1<75f16a94?=h:m=1<75rb213>5<2290;w)N48o1C>k74$0:6>=25<5<5;h0e4?6=3f8o;7>5;|`06g<72<0;6=u+2g:95a3<@::m7Ei950;9~f64d290>6=4?{%0e221>0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg55l3:187>50z&1b=<6l01C?=h4H3d:?l7013:17d?8a;29?l4a83:17b0;684?:1y'6c>=9m?0D>>i;I0e=>"60<0:995f16;94?=n9>k1<75f16`94?=n9>i1<75`2e594?=zj:836=4::183!4a03;o96F<0g9K6c?<,82>65:4i05:>5<5<5<54;294~"5n10:h45G31d8L7`>3`;<57>5;h34e?6=3`8m<7>5;n0g3?6=3th=4>4?:583>5}#:o21=i<4H22e?M4a12.:484>429j52?=831b=:o50;9j52d=831d>i950;9~f3>3290?6=4?{%0e2900e<9n:188m7`72900c?j8:188yg0?83:187>50z&1b=<6l;1C?=h4H3d:?!7?=3;??6g>7883>>o6?h0;66g>7c83>>i5l>0;66sm69394?2=83:p(?h7:0f:?M57n2B9j45f16;94?=n9>k1<75f2g294?=h:m=1<75rb74;>5<3290;w)N48o1C>k74$0:6>4243`;<57>5;h34e?6=3`;5;n0g3?6=3th=:44?:583>5}#:o21=i74H22e?M4a12c:;44?::k23d<722c9j=4?::m1`2<722wi:;;50;694?6|,;l36N5n01/=5;51518m41>2900e<9n:188m41e2900c?j8:188yg01>3:187>50z&1b=<6l01C?=h4H3d:?l7013:17d?8a;29?l4a83:17b=9m?0D>>i;I0e=>"60<08h6g>7883>>o6?h0;66g>7c83>>o6?j0;66a=d683>>{e31<75f16c94?=n:o:1<75`2e594?=zj<;=6=4::183!4a03;o96F<0g9K6c?<,82>69o4i05:>5<5<5<55;294~"5n10:h85G31d8L7`>3-;397:7;h34=?6=3`;5;h34f?6=3`;5;n0g3?6=3th>=54?:583>5}#:o21=i74H22e?M4a12c:;44?::k23d<722c9j=4?::m1`2<722wi8o750;794?6|,;l36N5n01/=5;5a:k23<<722c:;l4?::k23g<722c:;n4?::m1`2<722wi8oo50;694?6|,;l36N5n01/=5;5f:k23<<722c:;l4?::k23g<722e9h:4?::a0gd=83>1<7>t$3d;>4b>3A9;j6F=f89j52?=831b=:o50;9j6c6=831d>i950;9~f151290>6=4?{%0e22=h0e<96:188m41f2900e<9m:188m41d2900c?j8:188yg24?3:187>50z&1b=<6l01C?=h4H3d:?l7013:17d?8a;29?l4a83:17b=9m=0D>>i;I0e=>"60<0:::5f16;94?=n9>k1<75f16`94?=n9>i1<75`1bf94?=zj<:?6=49:183!4a03;o:6F<0g9K6c?<,82>685f16;94?=n9>k1<75f16`94?=n9>i1<75`1bf94?=h:m=1<75rb7;4>5<3290;w)N48o1C>k74$0:6>745<5<=57>54;294~"5n10:h95G31d8L7`>3-;397;k;h34=?6=3`;5;h34f?6=3f;hh7>5;|`72f<72<0;6=u+2g:95a1<@::m7Em1b=:750;9j52g=831b=:l50;9j52e=831d=nj50;9~f376290=6=4?{%0e2B822<<0e<96:188m41f2900e<9m:188m41d2900c2;292?6=8r.9j54>d79K75`<@;l27)?75;;7?l7013:17d?8a;29?l70j3:17d?8c;29?j7dl3:17b=9m<0D>>i;I0e=>"60<0>:6g>7883>>o6?h0;66g>7c83>>o6?j0;66a>ce83>>i5l>0;66sm60c94?0=83:p(?h7:0f5?M57n2B9j45+1979=1=n9>31<75f16c94?=n9>h1<75f16a94?=h9jn1<75`2e594?=zj?;>6=49:183!4a03;o:6F<0g9K6c?<,82>6884i05:>5<5<5<t$3d;>4b03A9;j6F=f89'5=3=9=h0e<96:188m41f2900e<9m:188m41d2900c50z&1b=<6l>1C?=h4H3d:?!7?=3;?56g>7883>>o6?h0;66g>7c83>>o6?j0;66a>ce83>>{e;j31<7;50;2x 7`?28n<7E=?f:J1b<=#91?1=9l4i05:>5<5<5<55;294~"5n10:h:5G31d8L7`>3-;397?;9:k23<<722c:;l4?::k23g<722c:;n4?::m2ga<722wi?i950;794?6|,;l36N5n01/=5;515`8m41>2900e<9n:188m41e2900e<9l:188k4ec2900qo=j3;291?6=8r.9j54>d69K75`<@;l27)?75;37g>o6?00;66g>7`83>>o6?k0;66g>7b83>>i6km0;66sm3d794?3=83:p(?h7:0f4?M57n2B9j45+197951d5<5<t$3d;>4b03A9;j6F=f89'5=3=9=h0e<96:188m41f2900e<9m:188m41d2900c50z&1b=<6l>1C?=h4H3d:?!7?=3;?56g>7883>>o6?h0;66g>7c83>>o6?j0;66a>ce83>>{e<9;1<7;50;2x 7`?28n<7E=?f:J1b<=#91?1=9l4i05:>5<5<5<:<7>55;294~"5n10:h:5G31d8L7`>3-;397?81:k23<<722c:;l4?::k23g<722c:;n4?::m2ga<722wi:N5n01/=5;5579j52?=831b=:o50;9j52d=831b=:m50;9l5fb=831d>i950;9~f1?>290=6=4?{%0e2B8228=;7d?89;29?l70i3:17d?8b;29?l70k3:17b?ld;29?j4c?3:17pl;9b83>1<729q/>k651e68L66a3A8m56*>848202=n9>31<75f16c94?=n9>h1<75`1bf94?=zj=3?6=4::183!4a03;o;6F<0g9K6c?<,82>68k4i05:>5<5<5<297>55;294~"5n10:h:5G31d8L7`>3-;397;j;h34=?6=3`;5;h34f?6=3`;5;n3``?6=3th?5;4?:483>5}#:o21=i94H22e?M4a12.:484:e:k23<<722c:;l4?::k23g<722c:;n4?::m2ga<722wi85750;794?6|,;l36N5n01/=5;55b9j52?=831b=:o50;9j52d=831b=:m50;9l5fb=831vn96n:186>5<7s-8m47?k7:J04c=O:o30(<6::4a8m41>2900e<9n:188m41e2900e<9l:188k4ec2900qo:7b;291?6=8r.9j54>d69K75`<@;l27)?75;7`?l7013:17d?8a;29?l70j3:17d?8c;29?j7dl3:17pl;8b83>0<729q/>k651e58L66a3A8m56*>8486g>o6?00;66g>7`83>>o6?k0;66g>7b83>>i6km0;66sm4c294?3=83:p(?h7:0f4?M57n2B9j45+19791f=n9>31<75f16c94?=n9>h1<75f16a94?=h9jn1<75rb5`2>5<2290;w)N48o1C>k74$0:6>0e5<5<5;h34e?6=3`;5;h34g?6=3f;hh7>5;|`72a<72=0;6=u+2g:95a2<@::m7E3`;<57>5;h34e?6=3`;5;n3``?6=3th?;84?:583>5}#:o21=i:4H22e?M4a12.:4846;h34=?6=3`;5;h34f?6=3f;hh7>5;|`0ef<72<0;6=u+2g:95a1<@::m7E6=4?{%0e228?n7d?89;29?l70i3:17d?8b;29?l70k3:17b?ld;29?xd1;<0;684?:1y'6c>=9m90D>>i;I0e=>"60<09;6g>7883>>o6?h0;66g>7c83>>i6km0;66a=d683>>{e<8;1<7;50;2x 7`?28n<7E=?f:J1b<=#91?1=9j4i05:>5<5<5<2i7>55;294~"5n10:h:5G31d8L7`>3-;397:7;h34=?6=3`;5;h34f?6=3`;5;n3``?6=3th>=94?:583>5}#:o21=i?4H22e?M4a12.:484=2:k23<<722c:;l4?::m2ga<722e9h:4?::a15>=83<1<7>t$3d;>4b13A9;j6F=f89'5=3=m2c:;44?::k23d<722c:;o4?::k23f<722e:oi4?::m1`2<722wi8?850;794?6|,;l36N5n01/=5;51628m41>2900e<9n:188m41e2900e<9l:188k4ec2900qo;80;291?6=8r.9j54>d69K75`<@;l27)?75;;0?l7013:17d?8a;29?l70j3:17d?8c;29?j7dl3:17pl:6483>0<729q/>k651e58L66a3A8m56*>84811>o6?00;66g>7`83>>o6?k0;66g>7b83>>i6km0;66sm62194?0=83:p(?h7:0f5?M57n2B9j45+19795025<5<5<7>56;294~"5n10:h;5G31d8L7`>3-;397?9b:k23<<722c:;l4?::k23g<722c:;n4?::m2ga<722e9h:4?::p253=838pR;>:;<73g?4c?2wx?9750;51[53127=o9478:?6g0o5478:?6g<ol478:?6ggon478:?6gaoh478:?6gco;478:?6g2h=478:?661>>478:?64a=n478:?65c?278944=fb9>70g=:oi01>;m:3d`?852m38mo63<5b81bf=:;km4=27e>7`d349=<7ho478:?6`fhi478:?6``hk478:?6a5i<478:?6a79;478:?6129l478:?61g9n478:?61a9h478:?61c:=478:?62495478:?61<4n478:?65=478:?6=45?478:?6=659478:?6=05;478:?6=24h478:?6478:?70d:777;<7`0???34?h9777;<7`777;<7;g???34?3h777;<7:4???34?2=777;<7:6???34?2?777;<7:0???34?29777;<7:2???34?2;777;<7;a???34?3j777;<62e???3492h777;<1:a???3492j777;<1b4???349j=777;<1b6???349j?777;<1b0???34>:n777;<756?70127?m<468:?7027?5<4=db9>0=3=111685=5999>0=7=11168:h5999>0=b=:mi019oj:8:891gd202019on:8:891g?20201;>k:8:891d228=37p}9b883>7}Y>k301;ln:3f4?xu1800;6?uQ61;893?c2;n<7p}9bc83>7}Y>kh01;ll:3f4?xu18?0;6?uQ6148906e28=j7p};4b83>7}:<=i1>ij4=42a>41>3ty>>>4?:3y>175=:mn019=?:05a?xu39k0;6;u26729=g=:k>4=5d2>7`734>:n78516`8yv23i3:1>v3;4`81`a=:=8n1=:m4}r167?6==r7?884<029>013=;9>019:::226?823=39;;63<5281`2=z{:?=6=4;{<162?4cl27?884>4g9>013=9<:0187l:05:?xu4=>0;69u234:96a1<5=2<6<9n;<6;7`9~w0b7290>w0;k0;0g`>;3<<09jh5245796c`<5=>>6>>?;<671?57:2wx9?:50;1x933a20801;8?:80890432;no7p}99c83>6}:>0h1>ij4=7;7>41f34<297?89:p25d=83;>w08?c;0g`>;1jh0:;l52503952?<5<:h6<9m;<43e?70i27>5n4>7c9>2=0=9>3018?j:05:?836=3;41?34?9:7?8b:?7`3<6?j169h:516`8906328=h70867;34e>;1;<0:;l52506952g<5<:36<9m;<406?70j2wx:4o50;0x93?f2;no70876;34g>{t>:>1<7jt=44g>41>34?=n7?89:?63c<6?0169:j516;8901e28=270;89;34=>;2?>0:;452567952?<5<=86<96;<745?70127>:k4>789>13>=9>301;=::3f4?xu11:0;6<6t=4a7><4<564<4=4a;><4<5<4<5<4<5<4<5<4<5m54>7`9>1d?=9>k018on:05b?83fj3;41f34<2977:187835<33i70;=6;0g3>;11<0:;l52686952e:m7>5az?51c<>j27?ih4=f19>04g=:mn019=l:05:?821n3;41d349i=7?8b:?763<6?01v;8?:181801838oh63;36823<=z{?:<6=4={<717??e34?9977c9~w12e2909w0:;b;0g`>;2:80:;l5rs56f>5<5s4>?979<;<67a?4cl2wx:=k50;1x936d20h01;>k:8`8936a2;n<7p}9b983>1}Y>k2019:::d3893562;n<70:6e;34f>{t>k<1<7=t^7`5?823=3o;708<0;0g3>{t>k?1<7=t^7`6?823=3nm708=f;0g3>{t>k>1<7=t^7`7?823=3nn708=e;0g3>{t>k91<7;t^7`0?823=3no708=d;0g3>;3000:;l524c2952g7>56z\5f7=:<=?1h45263a96a1<5=3=6<9n;<6;e?70i27?n<4>7`9~w3d6290=wS8m1:?700o4=d69>0<3=9>k0196m:05b?82e:3;41f34>3o7?8a:p2d0=83=pR;o9;<671?1534>247?89:?7=d<6?j1684l516;8910228=j708=9;0g3>{t>h>1<79t^7c7?823=3=:70:68;34e>;31h0:;l5248`952g<5=<>6<9m;<412?4c?2wx:l=50;5xZ3g434>?979i;<6:789>0h01;<<:3f4?82>k3;<56s|6`094?5|V?k970:;5;5f?806m38o;6s|6`394?2|V?k:70:;5;5g?806l38o;63;98823f=z{?k;6=4>4z\5e5=:<=?1;n5247:952?<5=7c9>03`=9>h0197i:05:?82f:3;1=:l4=5;6>41e34>2:7?8b:?7<<<6?k1685o516`891>e28=i70:7c;34f>;3j90:;o524c3952d<5=h96<9m;|q5=c<728=47?8a:?556<5l>168;9516c8910e28=i70:9f;34g>;3?:0:;n5248d952g<5=k96<9l;<6a7?70k27?:n4>7b9>0<2=9>i0197::05`?82>>3;41d34>3o7?8c:?7f5<6?j168o?516a891d528=h7p}99d83>a}Y>0o019:::6c8910e28=j708>0;0g3>;3>909hh52475952?<5=3j6<9m;<6:f?70k27?9o4>789>00b=9>301986:05a?821k3;;20o09hi5252d952?53z\6a3=:=1o1>ij4=40:>41>3ty>j<4?:2y]1c7<5<3<6?jk;<70f?7012wx9k>50;1xZ0`734?2:7584=de9>161=9>30q~;je;297~X2ml1694:52ef8905228=27p}:ee83>6}Y=ln0187<:3fg?834;3;<56s|5da94?5|V;2;80:;45rs4ga>5<4sW?nn63:9081`a=:=;l1=:74}r7fe?6=;rT>il5258296ab<5<8o6<96;|q6a<<72:qU9h74=4:g>7bc34?9n7?89:p1`3=83>pR8k:;<7;g?4cl27>:54>7`9>16e=9>20q~;ib;2966}Y=oh019k::3d3?82a83;41e34>mh7?8a:?7fa<6?0168om516`891`b28=i70:ic;34f>;3nk0:;o524e:952?<5=ni6<96;<6`2?70k27?o:4>7b9>151=9>3019?i:05`?82483;41>34>n?7?8a:?65<<6?016947516;891ea28=i70:mf;34=>;3l:0:;4524b;952?<5=826<9l;<736?4a827><;4=f19>0a7=:o:019lm:3d3?82c>3;<56s|5g;94?45sW?m563;e9823<=:41f34>m?7?8a:?7b1<6?h168kj516;891dc28=j708ma;34=>;3jj0:;4524ga952?<5=o96<9n;<6e=?70127?h54>7b9>157=9>3019jm:05b?82d>3;41>349>?7?89:?7g7<6?h168h8516;8907>28=j70;69;34f>;3ko0:;l524cd952g<5=n86<9n;<6`=?70j27?>44>7`9>0c`=9>i019j?:05a?82c>3;41>34>mm7?89:?7b=<6?k168k9516a891`128=i70:i5;34=>;3nl0:;4524g`952?<5=n26<9m;<6ge?70j27><<4>7`9>0a`=9>h019m9:05a?837?3;41>34>nh7?8c:?7g6<6?0168n:516;891c028=h70:j3;34g>;21h0:;n5258`952?<5=n96<96;<6`4?70k27?o<4>789>0a2=9>3019j::05:?82ck3;41>34?;97?8b:?7`5<6?0169<8516c8907028=270:m9;34g>;3jh0:;o5rs4d4>5<5irT>j:524eg952?<5=no6<9n;<6ee?70i27?j54>7b9>0c1=9>k019h9:05:?82a=3;41>34>om7?89:?644<6?k168ih516c891e028=j70:l8;34e>;28>0:;l524d6952?<5=i>6<9l;<6g3?70i27?ii4>789>0f5=9>k019m;:05b?82b?3;<563;e2823<=:=0k1=:o4=4;a>41f34>o>7?8c:?7g5<6?k168n?516c891b328=j70:k5;34f>;3lj0:;o524c:952?<5=o;6<96;<6eb?70i27><84>7`9>0a6=9>k018?9:05a?836?3;41e34>m47?89:?7f`<6?j168k9516;891`128=h70:i5;34g>;3nl0:;l524g`952e<5=n26<9l;<6ge?70i27><<4>7b9>0a`=9>i019m8:05:?82d03;0<1=:o4=5g7>41f34>h97?8a:?7`2<6?k168hj516`891e428=i70:j7;34f>;3m:0:;o5250;952d<5<3j6<96;<7:f?70j27?h?4>7`9>0f6=9>3019m>:05a?82c<3;41f34>n<7?8b:?7bc<6?k169=;516;891b728=h70:m9;34=>;3jh0:;45rs4d6>5<59rT>j8524cg952?<5=l<6<9m;<6e2?70i27?j84>7c9>0`4=9>h019hm:05b?82c13;41>34>n87?8b:?7g0<6?0168i9516a8963328=h70:jd;34e>;28:0:;l524b1952e<5=i?6<9m;<6f3?70i27?i;4>7c9>14?=9>i0187n:05a?83>j3;41d34>i47?8c:?7a5<6?j169=>516;8906228=h70:m9;34f>;28=0:;o5rs7ce>5<5sWe`823<=z{?ko6=4={_4b`>;6m00:;45rs7c`>5<5sWe9823<=z{?ki6=4={_4bf>;6m>0:;45rs7cb>5<5sWe7823<=z{?k26=4={_4b=>;6m<0:;45rs7c;>5<5sWe5823<=z{?k<6=4={_4b3>;6m:0:;45rs56:>5<5s4>?97m:;<67=?4cl2wx89650;0x91222j>019:7:3fg?xu3<>0;6?u24579a6=:<==1>ij4}r672?6=:r7?884j2:?703<5lm1v>:n:187856938o463;44840>;2:>0j=6399`8:f>{t>131<7c6<5<13e=9>k0q~862;296~;3<<0:52z?700<68m169:k516c8yv0>83:1?v3;44824f=:9o81=:l4=45`>41f3ty=4k4?:2y>013=99h01:05a?830i3;>6<>n;<3e4?70j27>;54>7`9~w3>c2908w0:;5;33=>;6mo0:;o52564952g53z?700<68116=hk516`8901328=j7p}98c83>6}:<=?1==:4=0gg>41e34?<>7?8a:p2=g=839p19:::g;894cd28=i70;80;34e>{t>1=1<7=t=566>`c<58oi6<9m;<753?70i2wx9i750;1x91222?9018k=:3fg?83fm3;<56s|5e:94?2|5=>>6;<4=4g2>7bc34?jh7?89:?6e0{t=m<1<7:t=566>3`<5m>4n1:p1a3=83>p19:::7g890bb2;no70;na;34=>;2i;0j=6s|5e694?2|5=>>6;j4=4fg>7bc34?j57?89:?6e4{t=m81<7:t=566>3d<55k4n1:p1a7=83>p19:::7c890bf2;no70;n6;34=>;21l0j=6s|55a94?4|5{t=7bc34<3?7?8a:p102=838p188?:3fg?80?83;7b9~w0352908w0;:e;0g`>;1?h0:;o5266`952e=7>53z?61a<5lm16::9516`8931?28=h7p}:5183>6}:=ij4=757>41e34<<97?8c:p11`=839p18;m:3fg?80093;n6=4<{<76e?4cl27=:h4>7c9>23`=9>i0q~;;d;297~;2=>09hi5267`952d<5?{t>?=1<7230=:m=0q~872;296~;2ko02n6398581`2=z{?=m6=4={<7`a??e34<3=77}:=ji15o5266;96a152z?6gg<>j27=;;4=d69~w3142909w0;la;;a?800;38o;6s|66294?4|57b03ty=:i4?:3y>1f>=1k16:;j52e58yv01i3:1>v3:c48:f>;1>h09h:5rs742>5<5s4?h877m;<455?4c?2wx9k:50;cxZ0`3349o:7?8a:?562<6?k16:?6516a8962428=i70=;4;34g>;1>00:;l52623952?<5<;1:=0:;o52637952e<5?<=6<9n;<117?70127>:n4>789~w363290iwS8?4:?56c<6?k16?oo516c896cb28=j708=1;34f>;1:;0:;n5232`952d<5:9h6<9l;<4;0?70i278><4>789>1=6=9>30q~8?3;29e~X18:16:?k516`896c728=j70=<7;34f>;4;10:;n52693952g<5:;m6<96;<414?70i27>;h4>789>24`=9>30q~8?2;2956}Y>9801>;6:063?852i3;?<63<5c8205=:;4=27`>427349>h7?;0:?01c<6<916?;>5152896b528=j7088d;34g>;1?l0:;o5260`952d<5?;h6<9l;<107?70j278?94>7b9>27b=9>301>?k:05:?830k3;<56s|61394?73sW<;=63<58827c=:;h4=27a>45a349>i7?;4k=0:;l52412952g<5?=j6<9l;<44f?70j278>k4>7c9>766=9>i01;831=:74=73b>41f3ty=<=4?:06xZ367349>57?;4=m0:?h5234d956c<5:<;6<=j;<1a2?70i278j?4>7`9>221=9>i01;97:05a?855j3;;h1=:74=735>41f349:57?89:?63=<6?016:<;516;8yv3an3:1=9uQ5gd8963>289o70=:a;30`>;4=k0:?i5234g956b<5:?h6<=k;<16`?74l2789k4>3e9>736=9:n019>?1=:l4=204>41e349947?8c:?56d<6?016?<9516;8901128=2708>1;34=>;19;0:;l5rs71g>5<>s49=<7;4<:0:;452356952d<5?9:6<9m;<111?70j2wx:>m50;cx963a2;l8708<0;34e>;4k10:;n523ga952e<5?=26?h?;<10b?7012788=4>7c9>272=9>301;<::05a?855;3;7b9>7`c=9>i01;99:3d3?80593;<563923823g=:;:h1=:74=21`>41e3499=7?8b:p26g=833p1>;k:3d0?805m3;>91>k>4=214>41>349847?8b:?05c<6?k16:?>516a8937a28=h7p}93883><}:;k=4=2f1>41d34<<<7;1:m0:;o5230f952d5az?01g<5n:16?n:516a8916728=h7089d;0e4>;4:o0:;452322952d<5?8h6<9m;<12f?70j27==44>7b9>24g=9>i0q~8<7;29e~;4=h09j>523c4952e<5:l96<9l;<45e?4a8278>o4>789>77e=9>h01;3;8?1=:m4}r402?6=ir78944=f29>07g=9>i01>k;:05`?801938m<63<26823<=:;;21=:l4=70b>41e349:;7?8b:?554<6?j16:<<516a8yv03=3:1?v3<61827f=:>;31>k>4=266>7`73ty=894?:2y>70`=9:i01>:>:3d3?805>38m<6s|65194?5|5:?n6<=l;<417?4a8278?i4=f19~w325290?w0=:d;30g>;19l0:;45232;96c6<5=326<96;|q504<72:q6?8m512a8937c2;l;70=<5;0e4>{t>=:1<78t=27a>45d34<:;7?89:?55=<6?016?>?52g28911528=j70:84;34e>{t>:l1<7:t=27b>45d34<:?7?89:?551<6?016??j52g28yv04m3:1:v3<58827f=:>8:1=:74=5:4>41>34>347?89:?7=a<6?016??752g28yv55<3:14v3<758b5>;4:<09h:5241d952?<5:=o6<9m;<62a?70j278m44>7b9>7c`=9>h019?>:05`?xu4:;0;6;u23619e4=:;;91>i94=52f>41d349;4:809h:5236`952d<5:l;6<9l;<1f7?70k278jk4>7b9~w67b29041e349m=7?8b:?0ef<6?k1v>?l:18485083k:70=>d;0g3>;38l0:;o5236;952d<5:n?6<9l;<1`3?70j278i>4>7c9~w67f290=w0=9f;c2?856j38o;63<79823g=:;j<1=:m4=2`:>41e349o97?8c:p74>=838j:`38967>2;n<70=87;34f>;4j10:;n523`:952e<5:i<6<9l;|q053<72>q6?;j5a09>741=:m=01>ok:05a?827j3;41d3ty88?4?:5y>05`=9>h01>:::3f4?826:3;72e=9>i019>>:05`?xu4;h0;69u232f96a1<5:om6<9l;<14f?70k278j>4>7b9~w651290?w0=j1;34f>;4;009h:5236c952e<5:o>6<9l;|q077<72=q6?i=516`896522;n<70=89;34g>;4l>0:;n5rs20f>5<3s498=728=h7p}<2`83>1}:;k=1=:l4=20g>7b0349<;7?8c:?0fg<6?j1v><9:186855138o;63<77823f=:;hn1=:m4=2`3>41d349i=7?8c:p00?=838p198=:3fg?802l3;;1=>0:;l5rs575>5<5s4>>j77`9~w1342909w0::a;0g`>;15<5s4<>h7e8823g=z{??36=4={<46=?4c?27:i54>7c9~w3312909w08:7;0g3>;6m>0:;o5rs777>5<5s4<>97e4823g=z{??;6=4={<465?4c?27:i94>7c9~w32b2909w08;f;0g3>;6m:0:;o5rs2;`>5<4s4;m>7?8a:?0e1<5lm168>:52g28yv5>j3:1?v3>f0823d=:;h91>ij4=510>41f3ty85l4?:2y>5c6=9>k01>o=:3fg?824;3;789~w6??2908w0?je;34e>;4i909hi52427952g53z?2aa<6?h16?4h52ef8915228=i7p}<9783>6}:9li1=:o4=2;f>7bc34>897?8c:p7<3=839p1l38oh63;32823<=z{=?96=4={<666?4cl27=:54>7c9~w1362909w0::1;0g`>;1><0:;o5rs573>5<5s4>><77c9~w6362909w0:;5;31`>;1=k0:;o5rs273>5<5s4>?97?=c:?51<<6?k1v>:i:181823=3;9n63956823g=z{:>n6=4={<671?75i27=984>7c9~w62c2909w0:;5;312>;1=:0:;o5rs26`>5<5s4>?97?>b:?514<6?k1v>:m:181823=3;:<6394g823g=z{7}:=jl1>ij4=566>f47>52z?6g`<5lm1689;5c09~w0e62909w0;ld;0g`>;3<<0h<6s|5b294?4|5nk4?:3y>1fd=:mn019:::cg8yv3em3:1>v3:c`81`a=:<=?1ni5rs4`g>5<5s4?h57>6lj4}r7ao94=de9>013=i;1v8hj:18`[3am278944:5:?01d<2=2789o4:5:?01`<2=2789n4:5:?01a<2=2789k4:5:?025<2=27=;<4>7b9>224=9>h0189;:05:?xu2nm0;6nuQ5gf8963>2<>01>;n:468963e2<>01>;j:468963d2<>01>;k:468963a2<>01>8?:468930b28=h7089f;34f>;2?;0:;45rs4d`>5;4=h0>?63<5c867>;4=l0>?63<5b867>;4=m0>?63<5g867>;4>90>?6396c823f=:>?i1=:l4=453>41>3ty>j?4?:by]1c4<5:?268<4=27b>04<5:?i68<4=27f>04<5:?h68<4=27g>04<5:?m68<4=243>04<5<<=6<96;<456?70k27=:>4>7c9~w32c2909w0=90;;a?87b:38o;6s|65a94?4|5:?m64l4=0g2>7b03ty=8o4?:3y>70c=1k16=h>52e58yv03i3:1>v3<5e8:f>;6lo09h:5rs76:>5<5s49>o77m;<3ga?4c?2wx:9650;0x963e20h010;6?u234c9=g=:9mi1>i94}r472?6=:r789446b:?2`g<5l>1v8k<:18b83ci33970;kb;;1?83ck33970;kd;;1?83cm33970;kf;;1?83b833970;j1;;1?83b:33970;j3;0g3>{t=9o1<7;29109j=5rs42g>5<4s4?;h7v3:1g8:f>;2:909h:5rs43g>5<5s4?:o77m;<72`?4c?2wx9d;34e>;2:80:;o5rs430>5<5s4?:>77m;<721?4c?2wx9<>50;0x906a20h018?>:3f4?xu29;0;6nu250096ab<5<;:6<9m;<73g?70i27>>;4>7`9>2=0=9>h018?j:05a?836=3;<563:24823<=:=;81=:74=716>41>34?:87?89:?577<6?h1v8>i:18g837n38oh63:10823d=:=9i1=:74=7:5>41f34?n?7?8a:?65`<6?h169?;516c8904528=j70;>6;34g>;29>0:;n52534952?<5<<>6<9n;<407?70j2wx>h950;0x90bf20h018oi:3f4?xu5m10;6?u25e`9=g=:=k:1>i94}r0f=?6=:r7>hn46b:?6f4<5l>1v?kn:18183cl33i70;m2;0g3>{t:lh1<71g2=:m=0q~76|5:;;6<99;<671?0334>?97o:;<671?g134>?97o8;<671?g?34>?97m9;<671?e034>?97m7;<671?e>34>?97k;;<671?c234>?97k6;<671?cf34>?973k:70;<8;c2?834i3k:70;=8;c2?824<3;071=9>k019<::05b?xu3j>0;6>u24ca952g<5=h36?j8;<7f0?7012wx>nh50;3:825:3;41f349jn7?8b:?0f7<6?j168?=516a8915528=j70:;38j0:;o52436952d<5:3:6<9l;<6`6?4c?2785>4>789>7<2=9>3019<7:05:?85f?38m<63<77823d=:;>=1=:o4=25;>41f349<57?8a:?03d<6?h16?:l516c8961d28=j70=8d;34e>{t9o<1<7?8{<1ba?70j27?><4>7`9>05b=9>301>om:05`?85e:3;41f34>9;7?8b:?0ed<6?k168?6516`891b42;n<70=nf;0e4>;3:<0:;4523c:952?<5:i=6<96;<1g0?701278i?4>789>7c6=9>301>hj:05:?85f03;7`9>0`2=:m=0q~<66;29=~;4=009ji5234c96cb<5:?i6?hk;<16a?4al2789n4=fe9>70b=:on01>;i:3dg?851838mh6390`81`2=z{=o26=4={<6e0?70127?ii4=d69~w1cf2909w0:i3;34=>;3n<09h:5rs5ga>5<5s4>m>7?89:?7b3<5l>1v9kl:18182a83;<563;f681`2=z{;3m6=4m{<1:`??53492i77=;<1:b??5349j<77=;<1b5??5349j>77=;<1b7??5349j877=;<6eg?4c?27??:4=f19>04b=9>k0q~;11=09h:5rs3ca>5<4s4?j:7m3:1?v3:9d81`2=:=0l158525c29=0=z{;kh6=4<{<7b3?4c?27>5k4=f19>1g6=9ji0q~;6f;297~;21o09h:525`29=0=:=k;1585rs3cg>5<4s4?j47m<4=f19>1g4=9ji0q~;n1;297~;2i809h:525`09=0=:=k91585rs3ce>5<4s4?jm7m>4=f19>1g2=9ji0q~;n3;297~;2i:09h:525`69=0=:=k?1585rs3`1>5<4s4?jo7m84=f19>1g0=9ji0q~;n5;296~;2i<09h:525c59=0=z{;h>6=4={<7ba?4c?27>n:4>cb9~w7??2909w0?i2;0g3>;6m;0:;45rs3;4>5<5s4;nm7e0823<=z{;8j6=4={<3f=?4c?27:i<4>7`9~w7662909w0?i0;0g3>;6m90:;45rs0d`>5<5s4;n47dg823<=z{;n86=4={<3f3?4c?27:hk4>7`9~w7b62909w0?je;0g3>;6ll0:;45rs3f3>5<5s4;n:7de823<=z{;hm6=4={<3f1?4c?27:hi4>7`9~w7d02909w0?jc;0g3>;6lj0:;45rs3c:>5<5s4;n87dc823<=z{8l>6=4={<3f7?4c?27:ho4>7`9~w7dd290:=v3>ec823<=:9li1=:74=0gg>41>34;ni7?89:?2ac<6?016=k>516;894`628=270?i2;34=>;3jj09h:521dc952g<58o26<9n;<3f7`9>5`0=9>k01e2823d=z{=o>6=4={<6f1?4c?27=789~w4`e2909w0:j8;0g3>;3m<0:;45rs0d0>5<5s4>n97?8a:?7a3<5l>1v9h>:18182a938o;63;ed823<=z{;h36=4={<6e0?4c?27?j<4>789~w7gf2909w0:i3;0g3>;3n80:;l5rs5ge>5<5s4>nj7:18182a:38o;63;eg823<=z{8lo6=4={<6e4?4c?27?ik4>7`9~w7?>2903w0:je;0g3>;11k09hh5268c96ac<5<<<6<9l;<401?70j27>:84>7c9>265=9>i01;==:05`?xu5890;67b034<9;7?8c:?56=<6?h16:??516a8934528=j708=4;34g>;1:<0:;l5260`952e<5?;h6<9n;<422?70127=>=4>789>247=9>k01;?=:05:?80613;8?1=:o4=73e>41f3ty9>94?:03x91be2;n<708=7;34e>;1:10:;452633952g<5?896<96;<410?70i27=>84>789>24d=9>k01;?l:05:?806>3;8;1=:l4=731>41e34<:57?8b:?55d<6?k16:<;516`8937a28=i7p}98483>43|5?2=6?j8;<44`?70127=;h4>7`9>22g=9>301;9m:05b?800?3;<563979823d=:>>>1=:74=756>41f34<<=7?89:?537<6?h16:;k516;8930a28=j7089b;34=>;1>j0:;l52670952?<5?<86<9n;<4;0?4a827=4<4=f19>23?=:o:01;89:3d3?xu5l;0;6>u24gc96a1<5=o=6<9l;<730?70i2wx>4l50;3582a038o;63;2`823<=:;kk1=:74=2`5>41>349h47?89:?0g1<6?016?i8516;896b528=270=j4;34=>;4m90:;4523g0952?<5:on6<96;<634?701278jn4>789>773=9>k01><<:05b?85593;41f349:57?8a:?052<6?h1v>:8:18a853038o;63<59823<=:>41>34<>57?89:?512<6?016:8;516;8933428=2708:1;34=>;154z?5ff<6?h16?8=516c891?b28=j70;?8;0g3>{t:h=1<7;t=7``>41>341}:i94=7;g>41>349?47?8c:?011<6?h1v?l6:18080ei3;i94}r0g0?6==r7=5i4>7b9>71>=9>3019k=:05:?852<3;<563;db81`2=z{;k>6=4>6z?5=1<6?016::j516c8931b28=27088a;34e>;1?k0:;452665952g<5?=36<96;<440?70i27=;84>789>227=9>k01;9=:05:?801m3;?h1=:o4=74`>41>34<=>7?8a:?526<6?016:5=516;893>728=270898;34=>;1><0:;45251696a153z?7``<5l>168ok516`893?128=i7p}=bc83>1}:i94=7;5>41d34?n87?8a:?641<6?01vo1=:m4=45`>41d34?;2?90:;n5262196a15bz?62f<6?k1695>516`8901b28=i70;8c;34f>;2?h0:;o5256:952d<5<==6<9m;<740?70j27>;?4>7c9>126=9>h01;==:3f4?xu6nh0;6:u268`9=g=:=?<1=:o4=444>41e34?n?7?8b:?7`3<5l>16:>=516;8935528=27p}=9d83><}:i94=713>41>34<9j7?89:?56`<6?016:?j516c8934d28=j708=b;34e>;1:h0:;l52623952g7>510y>154=:m=01>:<:05`?853<3;41d3498o7?8a:?072<6?j16?>6516c8965428=h70=<4;34e>;4:o0:;n52322952g<5:8i6<9l;<11g?70i278>:4>7b9>77>=9>k0q~i94=260>41f349?87?89:?07c<6?h16?9>516;8965e28=j70=;4;>0:;l5232:952?<5:986<9n;<100?701278>k4>7`9>766=9>301>>54=d69>16c=1<1v8=n:180834i38o;63:298:1>;2;m0296s|52:94?5|5<936?j8;<70e??234??477:;|q673<72:q69>852e58905?20?018:8:878yv34<3:1?v3:3581`2=:=:<158525549=0=z{<996=4<{<706?4c?27>?9465:?600<>=2wx9>>50;1x90572;n<70;<2;;6?833<33>7p}:2d83>6}:=;o1>i94=413><3<5<>864;4}r71g?6=;r7>>n4=d69>17c=1<1699<5949~w04f2908w0;=a;0g3>;2:j02963:408:1>{t=;=1<7=t=404>7b034?9m77:;<774??23ty>844?:3y>171=:o:018=l:3f4?xu2>:0;6iu25449=7=:=<=15?5254c9=7=:=53z?613<>j27>4n46b:?62=<5l>1v88i:180832?33i70;7d;;a?831n38o;6s|56394?5|51<7=1k169:=52e58yv30=3:1?v3:5b8:f>;21;02n63:7481`2=z{<=<6=4<{<76`??e34?2?77m;<743?4c?2wx9:750;1x903b20h0187;:8`8901>2;n<7p}:7c83>6}:=h1>i94}r74`?6=;r7>:=46b:?6=3<>j27>;i4=d69~w01a2908w0;91;;a?83>?33i70;8f;0g3>{t=?h1<7=t=47;>7b03ty>:i4?:2y>10?=1k1695h59c9>13b=:m=0q~;73;296~;2<909h:5257d952g52z?604<5l>169:?516c8yv3?=3:1>v3:4381`2=:=>91=:o4}r7;2?6=:r7>8>4=d69>123=9>k0q~;77;296~;2<=09h:52565952g52z?600<5l>169:7516c8yv3?13:1>v3:4781`2=:=>h1=:o4}r7;e?6=:r7>8:4=d69>12b=9>k0q~;7b;296~;2<109h:5256d952g52z?67a<5l>169;l516c8yv3?:3:1>v3:3d81`2=:=?n1=:o4}r7:4n462:?6:27>5=462:?6=4<>:27>5?462:?6=6<>:27>59462:?6=0<>:27>5;462:?6=2<>:27>4h462:?6:27>:?4>7`9>163;b481`2=z{=k?6=4:{<67b??e34>j470}:<<:15o524`c96ab<5=ki6<96;<65a?70i27?n?4>789~w1g1290>w0::1;;a?82fk38oh63;ae823<=:41>3ty?m:4?:4y>004=1k168lk52ef891ga28=270:99;34=>;3j90:;45rs55a>5<2s4>?:77m;<64b?4cl27?4=4>789>020=9>30196l:05:?xu3?j0;68u24559=g=:<1;1>ij4=5:1>41>34>=j7?89:?7;30=0:;45247a952?<5=2j6<96;|q73`<720=3=:mn01969:05:?82113;=m7=838p19;i:8`8910?2;n<7p};6783>7}:=87>55z?727<>j27?:=46b:?720<5l>1688j516`8913e28=i7p};9283>7}:<091>ij4=56g>3j7>55z?70g<>j27?4k4=de9>0<6=9>30199<:05:?82><3;<56s|47194?76s4>247;3i:0:;n52482952e<5=396<9l;<6;a?70k27?4;4>7b9>0=2=9>i0196=:05`?82?83;41d34>j57?8c:p0<1=838p197<:8`891?a2;n<7p};9083>0}:<=i15o5248396ab<5=396<96;<65a?70127?584>789~w1>c290>w0:;a;;a?82?l38oh63;8d823<=:41>3ty?m=4?:4y>01c=1k168l?52ef891g528=270:n3;34=>;3?=0:;45rs2;1>5<4s49=o77:;<141?70i2785>4=d69~w6?72908w0=9c;c2?850=3;<563<9081`2=z{:2i6=4={<15g?4a8278;84=d69~w60d2908w0=9c;0g3>;4>m02963<7d8:1>{t;1i1<7=t=24g>7`73491v>8k:180851l38o;63<6d8:1>;4?o0296s|39f94?5|5:;4>o02963<818:1>{t;1o1<7=t=24e>7`73493<7?lc:?03=<5l>1v>8i:180851n38o;63<718:1>;4080296s|39d94?5|5:=;6?h?;<1;5?7dk278;44=d69~w6172908w0=80;0g3>;4?802963<838:1>{t;1=1<7=t=252>7`73493>7?lc:?03d<5l>1v>9>:180850938o;63<738:1>;40:0296s|39:94?5|5:=96?h?;<1;7?7dk278;o4=d69~w6152908w0=82;0g3>;4?:02963<858:1>{t;131<7=t=250>7`7349387?lc:?03f<5l>1v>9<:180850;38o;63<758:1>;40<0296s|39c94?5|5:=?6?h?;<1;1?7dk278;i4=d69~w6132909w0=84;0g3>;40?0296s|37;94?g|5=886?j8;<1ag?701278ol4>789>7a>=9>301>k9:05:?85a<3;<563;03823<=:<9k1=:74=503>41>349j:7?89:p73>=83hp19<=:3f4?825?3;41>349in7?89:?0g<<6?016?i9516;896c228=270=i3;34=>;3880:;45rs244>5<>s49i>7;4l>0:;l523d7952g<5:l86<9n;<635?70i2wx?;850;;x96gb2;n<70:?f;34e>;4j?0:;o523b6952d<5:n96<9m;<1f4?70j278ih4>7c9>7ce=9>h01>ok:05b?xu4><0;64u241f96a1<5=:n6<96;<62a?701278n44>789>7f1=9>301>j::05:?85b;3;<5637g>=9>k01>m9:05b?85c<3;41f34>:=7?8a:p735=832p19<>:3f4?825i3;41f349n?7?8a:?0b4<6?h16?kh516c8yv51:3:15v341e349o:7?8b:?0a1<6?k16?k<516`8916728=i70:?e;34e>;4ij0:;l5rs242>5<4s4>8>78516a8yv5f=3:1>v3<9e8:f>;4i?09h:5rs2`6>5<5s492i77m;<1ag?4c?2wx?n=50;0x96?a20h01>mn:3f4?xu4l80;6?u23`29=g=:;m21>i94}r1gb?6=:r78m<46b:?0a3<5l>1v>kk:18185f:33i70=i4;0g3>{t;oh1<705g=:m=0q~:8i7>52z?03c<5l>16?om516a8yv24n3:1>v3<8181`2=:;jk1=:m4}r674?6=:r784<4=d69>7a>=9>i0q~:;1;296~;40;09h:523d4952e?>7>52z?0<6<5l>16?k:516a8yv23;3:1>v3<8581`2=:<981=:m4}r670?6=:r78484=d69>05g=9>i0q~:=f;297~;39h02>63;1c8:6>;3;909h:5rs51a>5<5s4>8o738o;63;21823f=z{:7c9~w1562909w0:>b;;a?824?38o;6s|40a94?4|5=;j64l4=503>7b03ty9n>4?:5y>0cc=:m=019hl:05b?826n3;4>7c9>0`5=:m=0q~52z?7`<<5l>168i6516`8yv4d83:1>v3;d`81`2=:<<4=d69>155=9>h018>?:05b?xu5k;0;6?u24ed96a1<5=ni6<9l;|q1g6<72;q68il516`891c72;n<7p}>fg83><}:9mh1>k>4=0f`>7`734;oh7;6m;09j=524cd96a151cy>074=9>301>8m:05:?85fm3;<563;20823<=:<9n1=:m4=2ca>41>349i>7?8a:?766<6?k168><516a8915d28=j70:?c;34=>;3:=0:;l52383952d<5:386<9n;<1:0?70i27?ok4=d69>07>=9>k01>o6:05b?850>3;<563<76823<=:;>21=:74=25:>41>349{t7b0349jm7?89:?7g<<6?h168?7516`8yv2di3:1:v3;fe81`2=:>0n1=:o4=5d;>41f34>ii7?8a:?00=<6?h16?lo516a8yv2dj3:1>v3;c9823f=:i94}r6`g?6=:r7?o54>789>0f1=:m=0q~:ld;290~;3k109h:523`c952g<5=i26<9l;<61=?7012wx>l=50;3;85fm3;41f349i>7?89:?766<6?h168><516`8915d28=i70:?b;34=>;3:=0:;452435952?<5:3:6<96;<6`=?4c?278n54>7c9>7f0=9>h01>j;:05a?85b:3;41f349i=7?8a:?0e=<6?016?l7516`8917628=i7p}:1`83>1}:=l91=:74=437>7b034?=97?89:?576<6?h1v8?m:180836138o;63:17823<=:=8=1=:l4}r60=?6=:r7??94=d69>060=9>k0q~:<8;296~;3;<09h:52424952?52z?6a6<6?j169h:51bf8yv37i3:1>v3:0681`2=:=921=:74}r73=?6=:r7><;4=d69>15>=9>i0q~868;296~;11?09h:52685952?52z?5=0<6?k16:4952e58yv4em3:1>v3:6d81`2=:=?n1=:l4}r75=?6=:r7>:54>7c9>133=9jn0q~;9a;296~;2>>09h:5257:952e52z?6=f<6?h1694752e58yv4d<3:1>v3;69823g=:03g=9>h0q~h0:;l5247a95fb54z?7<2<6?j16856516a891?c28=i708>1;0g3>{t:j21<7:t=733>41e34>347?8b:?7=a<6?j16:<<52e58yv5e<3:1>v37b9>7de=9jn0q~0:;l52460952d<5==?6<9l;<42=?4c?2wx>nm50;6x937028=i708>8;34f>;3?;0:;n5260c96a152z?556<6?h16:<;52e58yv4dm3:1?v391781`2=:>891=:l4=737>41e3ty8nk4?:3y>7g1=9>i01>l6:0ag?xu4k90;6?u23cc96a1<5:h<6<96;|q0g4<72;q6?o9516c896d12;n<7p}7}:;k=1>i94=2``>41e3ty8ni4?:3y>7g>=:m=01>lm:05a?xu4jl0;6?u23ca952g<5:hi67}:;j21>i94=2a6>41>3ty8ok4?:3y>7f3=9>k01>m;:3f4?xu4l90;6?u23b796a1<5:ij6<9m;|q0gg<72;q6?n852e5896e>28=i7p}7}:;jk1=:o4=2a:>4ec3ty8ho4?:3y>7a5=9>i01>j::0ag?xu4lj0;6?u23e496a1<5:n86<96;|q0`a<72;q6?i=516c896b52;n<7p}7}:;m91>i94=2f;>41e3ty8h44?:3y>7a2=:m=01>j8:05a?xu4lh0;6?u23e:952g<5:n<67}:;l>1>i94=2g2>41f3ty8io4?:3y>7`6=:m=01>k>:05:?xu4mj0;6?u23d396a1<5:o=6<9m;|q0a2<72;q6?h<52e5896c228=i7p}7}:;l<1=:o4=2g6>4ec3ty8j:4?:3y>7``=9>h01>h>:0ag?xu4n10;6?u23g096a1<5:om6<96;|q0b<<72;q6?hh516c896cb2;n<7p}7}:;ll1>i94=2d7>41e3ty8j84?:3y>7c6=:m=01>h<:05a?xu4n?0;6?u23g6952g<5:l867}:<9:1>i94=2dg>41>3ty?<:4?:3y>7cb=9>k01>hl:3f4?xu3810;6?u23gf96a1<5=:96<9m;|q746<72;q6?kk52e58916628=i7p};0583>7}:<981=:o4=522>4ec3ty?=84?:3y>05c=:m=019??:05:?xu3910;6?u241`96a1<5=;;6<9n;|q75<<72;q68=m52e58917728=i7p};1283>7}:<9l1>i94=533>41d3ty?=94?:3y>05g=9>h019??:0ag?xu39?0;6?u2400952d<5=;:6f983>7}:>8l1>i94=5;:>41e3ty:j44?:2y>276=:m=01;?j:05a?82>13;50;0x910a2;n<70::d;34e>{t<>=1<77b034>{t9oo1<7:t=546>41>34>257v3;2581`2=:<;?1=:l4}r61g?6=:r7?>84=d69>070=9>i0q~:=d;296~;39l0:;l5243495fb9i7>52z?76d<5l>168k>4=41g>4ed3ty>?o4?:2y>16d=:m=018=n:3d3?83303;ho6s|52;94?5|5<926?j8;<708:4>cb9~w0502908w0;<7;0g3>;2;?09j=5255495fe53z?670<5l>169>:52g28902228ih7p}:3283>6}:=:91>i94=411>7`734??87?lc:p167=839p18=>:3f4?834838m<63:4282gf=z{<8m6=4<{<71b?4c?27>>h4=f19>114=9ji0q~;=d;297~;2:m09h:5253a96c6<5<>:6{t=:l1<77b034?8i7?lc:p655=838p1>69:0a`?85><38o;6s|21694?0|5=2<6?j8;<6b7?70i27?mk4>7`9>0db=9>k019om:05b?82f13;7`9>0=4=9>k0196?:05b?xu58?0;6?u24`39=g=:i94}r033?6=:r7?9n46b:?71a<5l>1v?>7:181822i33i70::b;0g3>{t:931<7:t=5;g>7b034>2<7?8a:?7=7<6?h1685k516c8yv47i3:1>v3;9`81`2=:023=9>h0q~2>712;n<7p}=0g83>7}:<1915o5249696a152z?7<4<>j27?4?4=d69~w7762909w0:8f;;a?82?838o;6s|20094?4|5=2o64l4=5:f>7b03ty9=>4?:3y>0dc=1k168lh52e58yv46<3:1>v3;ab8:f>;3im09h:5rs336>5<5s4>jm77m;<6bf?4c?2wx><850;0x91g?20h019o6:3f4?xu59>0;6?u2477952e<5=3h6516`8917c28io7p}=1883>7}:<8l1>i94=503>41f3ty9=l4?:3y>0<`=9>h0197j:0ag?xu59k0;6?u24`096a1<5=k86<9m;|q15f<72;q684>516`891?328io7p}=1e83>7}:<081=:l4=5;6>4ec3ty9=h4?:3y>0=c=9>h01979:0ag?xu59o0;6?u2494952d<5=226f28io7p}=2083>7}:<181=:l4=5:a>4ec3ty9>?4?:3y>0=6=9>h0196l:0ag?xu5::0;6?u24`d952d<5=h;67}:4ec3ty9>:4?:3y>0g5=:m=019o6:05a?xu5:10;6?u23`d96a1<5:k=6<9m;|q16<<72;q68;k52e58910c28=j7p}=2c83>7}:;hn1>i94=2c`>41d3ty9>n4?:3y>020=:m=0199::05b?xu5:m0;6?u243596a1<5=8=6<9m;|q16`<72;q68?652e58914128=j7p}=2g83>7}:<8o1>i94=53g>41d3ty9?=4?:3y>0f`=9>3019j>:3f4?xu5;80;6?u257a96a1<5<52e58901a28=i7p}=3283>7}:=>o1>i94=45g>41e3ty9?94?:3y>12e=:m=0189m:05a?xu5;<0;6?u256c96a1<5<=26<9m;|q173<72;q69:652e58901028=i7p}=3683>7}:=><1>i94=456>41e3ty9?54?:3y>122=:m=0189<:05a?xu5;00;6?u256096a1<5<=:6<9m;|q17d<72;q69;h516`8901728io7p}=3c83>7}:=?<1>i94=446>41d3ty9?n4?:3y>143=9>h018?7:3f4?xu5;m0;6?u250g96a1<5<;o6<96;|q17`<72;q68i952e5891b128=i7p}=3g83>7}:;<>1>i94=270>41d3ty98=4?:3y>0f5=:m=019m=:05a?xu5<80;6?u24b696a1<5=i96<9l;|q107<72;q68h952e5891c128=j7p}=4283>7}:=0k1>i94=4;:>41f3ty9894?:3y>152e5891da28=h7p}=4683>7}:i94=5`e>41e3ty9854?:3y>07>=9>i019<6:3f4?xu5<00;6?u24e696a1<5=n86<9l;|q10d<72;q68i;52e5891b428=i7p}90e83>0}:>9n1>ij4=5d1>41d34>m87?8c:?7b5<6?j168k=516a8yv06;3:18v391581`2=:41d34>2o7?8b:p241=83>p1;?7:3f4?820>3;22e=9>30q~<;c;296~;1?l09h:5266a952g52z?53d<5l>16::7516;8yv43m3:1>v397c81`2=:>>31=:o4}r07b?6=:r7=;:4=d69>220=9>30q~<:0;296~;1?109h:52664952g=7>52z?531<5l>16::=516;8yv42:3:1>v397481`2=:>>91=:o4}r067?6=:r7=;<4=d69>226=9>30q~<:4;296~;1?;09h:52662952g97>52z?52`<5l>16:;j516;8yv42>3:1>v396g81`2=:>?n1=:o4}r063?6=:r7=:o4=d69>23g=9>30q~<:8;296~;1>j09h:5267c952g57>52z?527<5l>16:;?516;8yv42i3:1>v396281`2=:>?;1=:o4}r06f?6=:r78n=4=d69>7d`=9>30q~<:c;296~;4j809h:523`d952gh7>52z?664<5l>169?>516;8yv42m3:1>v3:2381`2=:=;:1=:o4}r06b?6=:r78m54=d69>7d1=9>30q~<91;296~;4i009h:523`5952g7>52z?7bc<5l>169=<516c8yv41;3:1>v3:0181`2=:=981=:74}r050?6=:r7??>4=d69>062=9>30q~<95;296~;28<09h:52514952?52z?562<5l>16:?7516c8yv41?3:1>v392981`2=:>;31=:74}r05<4=d69>275=9>k0q~<99;296~;1:;09h:52631952?52z?006<5l>16?9;516c8yv41j3:1>v3<4581`2=:;=?1=:74}r05g?6=:r78?k4=d69>717=9>k0q~<9d;296~;4<909h:52353952?52z?07g<5l>16?>j516c8yv41n3:1>v3<3b81`2=:;:n1=:74}r044?6=:r7=>94=d69>270=9>k0q~<81;296~;1:<09h:52634952?7>52z?55g<5l>16:v391b81`2=:>8n1=:74}r040?6=:r78?:4=d69>76?=9>k0q~<85;296~;4;109h:5232;952?52z?076<5l>16?>;516c8yv40?3:1>v3<3581`2=:;:?1=:74}r04k4=d69>767=9>k0q~<89;296~;4;909h:52323952?52z?06g<5l>16??j516c8yv40j3:1>v3<2b81`2=:;;n1=:74}r04g?6=:r78>:4=d69>77?=9>k0q~<8d;296~;4:109h:5233;952?52z?5<6<5l>16:5:516;8yv40n3:1>v398181`2=:>1;1=:74}r0;4?6=:r7=:54=d69>23?=9>30q~<71;296~;1><09h:52674952?7>52z?7`5<5l>168i?516;8yv4?;3:1>v3:1781`2=:=821=:o4}r0;0?6=:r7>=:4=d69>14>=9>30q~<75;296~;3j009h:524c`952g52z?7fd<5l>168ol516;8yv4??3:1>v3;3781`2=:<:=1=:o4}r0;<94>ce9>2<3=9>i0q~<79;296~;11>0:oi52686952d52z?554<6km16:<>516c8yv4?j3:1>v391382ga=:<1=1=:l4}r0;g?6=:r7==44>ce9>24>=9>k0q~<7d;296~;19h0:oi52466952d52z?550<6km16:<:516c8yv4?n3:1>v391g82ga=:>8o1=:o4}r0:4?6=:r7?544>ce9>0<>=9>i0q~<61;296~;1;<0:oi5258a952e7>52z?651<6km169;9516;8yv4>;3:1>v3:0982ga=:;<21=:o4}r0:0?6=:r7=?>4>ce9>13e=9>i0q~<65;296~;1;;0:oi5257g952d51zJ1b<=zfl:j6=4>{I0e=>{im9h1<7?tH3d:?xhb8j0;6k74}og25?6=9rB9j45rnd31>5<6sA8m56sae0194?7|@;l27p`j1583>4}O:o30qck>5;295~N5n01vbh?9:182M4a12wei<950;3xL7`>3tdn=54?:0yK6c?51zJ1b<=zfl;j6=4>{I0e=>{im8h1<7?tH3d:?xhb9j0;6k74}og15?6=9rB9j45rnd01>5<6sA8m56sae3194?7|@;l27p`j2583>4}O:o30qck=5;295~N5n01vbh<9:182M4a12wei?950;3xL7`>3tdn>54?:0yK6c?51zJ1b<=zfl8j6=4>{I0e=>{im;h1<7?tH3d:?xhb:j0;6k74}og05?6=9rB9j45rnd11>5<6sA8m56sae2194?7|@;l27p`j3583>4}O:o30qck<5;295~N5n01vbh=9:182M4a12wei>950;3xL7`>3tdn?54?:0yK6c?51zJ1b<=zfl9j6=4>{I0e=>{im:h1<7?tH3d:?xhb;j0;6k74}og75?6=9rB9j45rnd61>5<6sA8m56sae5194?7|@;l27p`j4583>4}O:o30qck;5;295~N5n01vbh:9:182M4a12wei9950;3xL7`>3tdn854?:0yK6c?51zJ1b<=zfl>j6=4>{I0e=>{im=h1<7?tH3d:?xhbk74}og65?6=9rB9j45rnd71>5<6sA8m56sae4194?7|@;l27p`j5583>4}O:o30qck:5;295~N5n01vbh;9:182M4a12wei8950;3xL7`>3tdn954?:0yK6c?57>51zJ1b<=zfl?j6=4>{I0e=>{imk74}og55?6=9rB9j45rnd41>5<6sA8m56sae7194?7|@;l27p`j6583>4}O:o30qck95;295~N5n01vbh89:182M4a12wei;950;3xL7`>3tdn:54?:0yK6c?51zJ1b<=zfl{I0e=>{im?h1<7?tH3d:?xhb>j0;6k74}og45?6=9rB9j45rnd51>5<6sA8m56sae6194?7|@;l27p`j7583>4}O:o30qck85;295~N5n01vbh99:182M4a12wei:950;3xL7`>3tdn;54?:0yK6c?51zJ1b<=zfl=j6=4>{I0e=>{im>h1<7?tH3d:?xhb?j0;6k74}og;5?6=9rB9j45rnd:1>5<6sA8m56sae9194?7|@;l27p`j8583>4}O:o30qck75;295~N5n01vbh69:182M4a12wei5950;3xL7`>3tdn454?:0yK6c?51zJ1b<=zfl2j6=4>{I0e=>{im1h1<7?tH3d:?xhb0j0;6b290:wEk74}og:5?6=9rB9j45rnd;1>5<6sA8m56sae8194?7|@;l27p`j9583>4}O:o30qck65;295~N5n01vbh79:182M4a12wei4950;3xL7`>3tdn554?:0yK6c?51zJ1b<=zfl3j6=4>{I0e=>{im0h1<7?tH3d:?xhb1j0;6l3:1=vF=f89~j`?b290:wEk74}ogb5?6=9rB9j45rndc1>5<6sA8m56sae`194?7|@;l27p`ja583>4}O:o30qckn5;295~N5n01vbho9:182M4a12weil950;3xL7`>3tdnm54?:0yK6c?51zJ1b<=zflkj6=4>{I0e=>{imhh1<7?tH3d:?xhbij0;6k74}oga5?6=9rB9j45rnd`1>5<6sA8m56saec194?7|@;l27p`jb583>4}O:o30qckm5;295~N5n01vbhl9:182M4a12weio950;3xL7`>3tdnn54?:0yK6c?51zJ1b<=zflhj6=4>{I0e=>{imkh1<7?tH3d:?xhbjj0;6k74}og`5?6=9rB9j45rnda1>5<6sA8m56saeb194?7|@;l27p`jc583>4}O:o30qckl5;295~N5n01vbhm9:182M4a12wein950;3xL7`>3tdno54?:0yK6c?51zJ1b<=zflij6=4>{I0e=>{imjh1<7?tH3d:?xhbkj0;6k74}ogg5?6=9rB9j45rndf1>5<6sA8m56saee194?7|@;l27p`jd583>4}O:o30qckk5;295~N5n01vbhj9:182M4a12weii950;3xL7`>3tdnh54?:0yK6c?51zJ1b<=zflnj6=4>{I0e=>{immh1<7?tH3d:?xhblj0;6k74}ogf5?6=9rB9j45rndg1>5<6sA8m56saed194?7|@;l27p`je583>4}O:o30qckj5;295~N5n01vbhk9:182M4a12weih950;3xL7`>3tdni54?:0yK6c?51zJ1b<=zfloj6=4>{I0e=>{imlh1<7?tH3d:?xhbmj0;6k74}oge5?6=9rB9j45rndd1>5<6sA8m56saeg194?7|@;l27p`jf583>4}O:o30qcki5;295~N5n01vbhh9:182M4a12weik950;3xL7`>3tdnj54?:0yK6c?51zJ1b<=zfllj6=4>{I0e=>{imoh1<7?tH3d:?xhbnj0;6k74}od35?6=9rB9j45rng21>5<6sA8m56saf1194?7|@;l27p`i0583>4}O:o30qch?5;295~N5n01vbk>9:182M4a12wej=950;3xL7`>3tdm<54?:0yK6c?51zJ1b<=zfo:j6=4>{I0e=>{in9h1<7?tH3d:?xha8j0;6k74}od25?6=9rB9j45rng31>5<6sA8m56saf0194?7|@;l27p`i1583>4}O:o30qch>5;295~N5n01vbk?9:182M4a12wej<950;3xL7`>3tdm=54?:0yK6c?51zJ1b<=zfo;j6=4>{I0e=>{in8h1<7?tH3d:?xha9j0;6k74}od15?6=9rB9j45rng01>5<6sA8m56saf3194?7|@;l27p`i2583>4}O:o30qch=5;295~N5n01vbk<9:182M4a12wej?950;3xL7`>3tdm>54?:0yK6c?51zJ1b<=zfo8j6=4>{I0e=>{in;h1<7?tH3d:?xha:j0;6k74}od05?6=9rB9j45rng11>5<6sA8m56saf2194?7|@;l27p`i3583>4}O:o30qch<5;295~N5n01vbk=9:182M4a12wej>950;3xL7`>3tdm?54?:0yK6c?51zJ1b<=zfo9j6=4>{I0e=>{in:h1<7?tH3d:?xha;j0;6k74}od75?6=9rB9j45rng61>5<6sA8m56saf5194?7|@;l27p`i4583>4}O:o30qch;5;295~N5n01vbk:9:182M4a12wej9950;3xL7`>3tdm854?:0yK6c?51zJ1b<=zfo>j6=4>{I0e=>{in=h1<7?tH3d:?xhak74}od65?6=9rB9j45rng71>5<6sA8m56saf4194?7|@;l27p`i5583>4}O:o30qch:5;295~N5n01vbk;9:182M4a12wej8950;3xL7`>3tdm954?:0yK6c?57>51zJ1b<=zfo?j6=4>{I0e=>{ink74}od55?6=9rB9j45rng41>5<6sA8m56saf7194?7|@;l27p`i6583>4}O:o30qch95;295~N5n01vbk89:182M4a12wej;950;3xL7`>3tdm:54?:0yK6c?51zJ1b<=zfo{I0e=>{in?h1<7?tH3d:?xha>j0;6k74}od45?6=9rB9j45rng51>5<6sA8m56saf6194?7|@;l27p`i7583>4}O:o30qch85;295~N5n01vbk99:182M4a12wej:950;3xL7`>3tdm;54?:0yK6c?51zJ1b<=zfo=j6=4>{I0e=>{in>h1<7?tH3d:?xha?j0;6k74}od;5?6=9rB9j45rng:1>5<6sA8m56saf9194?7|@;l27p`i8583>4}O:o30qch75;295~N5n01vbk69:182M4a12wej5950;3xL7`>3tdm454?:0yK6c?51zJ1b<=zfo2j6=4>{I0e=>{in1h1<7?tH3d:?xha0j0;6b290:wEk74}od:5?6=9rB9j45rng;1>5<6sA8m56saf8194?7|@;l27p`i9583>4}O:o30qch65;295~N5n01vbk79:182M4a12wej4950;3xL7`>3tdm554?:0yK6c?51zJ1b<=zfo3j6=4>{I0e=>{in0h1<7?tH3d:?xha1j0;6l3:1=vF=f89~jc?b290:wEk74}odb5?6=9rB9j45rngc1>5<6sA8m56saf`194?7|@;l27p`ia583>4}O:o30qchn5;295~N5n01vbko9:182M4a12wejl950;3xL7`>3tdmm54?:0yK6c?51zJ1b<=zfokj6=4>{I0e=>{inhh1<7?tH3d:?xhaij0;6k74}oda5?6=9rB9j45rng`1>5<6sA8m56safc194?7|@;l27p`ib583>4}O:o30qchm5;295~N5n01vbkl9:182M4a12wejo950;3xL7`>3tdmn54?:0yK6c?51zJ1b<=zfohj6=4>{I0e=>{inkh1<7?tH3d:?xhajj0;6k74}od`5?6=9rB9j45rnga1>5<6sA8m56safb194?7|@;l27p`ic583>4}O:o30qchl5;295~N5n01vbkm9:182M4a12wejn950;3xL7`>3tdmo54?:0yK6c?51zJ1b<=zfoij6=4>{I0e=>{injh1<7?tH3d:?xhakj0;6k74}odg5?6=9rB9j45rngf1>5<6sA8m56safe194?7|@;l27p`id583>4}O:o30qchk5;295~N5n01vbkj9:182M4a12weji950;3xL7`>3tdmh54?:0yK6c?51zJ1b<=zfonj6=4>{I0e=>{inmh1<7?tH3d:?xhalj0;6k74}odf5?6=9rB9j45rngg1>5<6sA8m56safd194?7|@;l27p`ie583>4}O:o30qchj5;295~N5n01vbkk9:182M4a12wejh950;3xL7`>3tdmi54?:0yK6c?51zJ1b<=zfooj6=4>{I0e=>{inlh1<7?tH3d:?xhamj0;6k74}ode5?6=9rB9j45rngd1>5<6sA8m56safg194?7|@;l27p`if583>4}O:o30qchi5;295~N5n01vbkh9:182M4a12wejk950;3xL7`>3tdmj54?:0yK6c?51zJ1b<=zfolj6=4>{I0e=>{inoh1<7?tH3d:?xhanj0;6=83;pD?h6;|l245?=83;pD?h6;|l245g=83;pD?h6;|l245d=83;pD?h6;|l245e=83;pD?h6;|l245b=83;pD?h6;|l245c=83;pD?h6;|l245`=83;pD?h6;|l2446=83;pD?h6;|l2447=83;pD?h6;|l2444=83;pD?h6;|l2445=83;pD?h6;|l2442=83;pD?h6;|l2443=83;pD?h6;|l2440=83;pD?h6;|l2441=83;pD?h6;|l244>=83;pD?h6;|l244?=83;pD?h6;|l244g=83;pD?h6;|l244d=83;pD?h6;|l244e=83;pD?h6;|l244b=83;pD?h6;|l244c=83;pD?h6;|l244`=83;pD?h6;|l2476=83;pD?h6;|l2477=83;pD?h6;|l2474=83;pD?h6;|l2475=83;pD?h6;|l2472=83;pD?h6;|l2473=83;pD?h6;|l2470=83;pD?h6;|l2471=83;pD?h6;|l247>=83;pD?h6;|l247?=83;pD?h6;|l247g=83;pD?h6;|l247d=83;pD?h6;|l247e=83;pD?h6;|l247b=83;pD?h6;|l247c=83;pD?h6;|l247`=83;pD?h6;|l2466=83;pD?h6;|l2467=83;pD?h6;|l2464=83;pD?h6;|l2465=83;pD?h6;|l2462=83;pD?h6;|l2463=83;pD?h6;|l2460=83;pD?h6;|l2461=83;pD?h6;|l246>=83;pD?h6;|l246?=83;pD?h6;|l246g=83;pD?h6;|l246d=83;pD?h6;|l246e=83;pD?h6;|l246b=83;pD?h6;|l246c=83;pD?h6;|l246`=83;pD?h6;|l2416=83;pD?h6;|l2417=83;pD?h6;|l2414=83;pD?h6;|l2415=83;pD?h6;|l2412=83;pD?h6;|l2413=83;pD?h6;|l2410=83;pD?h6;|l2411=83;pD?h6;|l241>=83;pD?h6;|l241?=83;pD?h6;|l241g=83;pD?h6;|l241d=83;pD?h6;|l241e=83;pD?h6;|l241b=83;pD?h6;|l241c=83;pD?h6;|l241`=83;pD?h6;|l2406=83;pD?h6;|l2407=83;pD?h6;|l2404=83;pD?h6;|l2405=83;pD?h6;|l2402=83;pD?h6;|l2403=83;pD?h6;|l2400=83;pD?h6;|l2401=83;pD?h6;|l240>=83;pD?h6;|l240?=83;pD?h6;|l240g=83;pD?h6;|l240d=83;pD?h6;|l240e=83;pD?h6;|l240b=83;pD?h6;|l240c=83;pD?h6;|l240`=83;pD?h6;|l2436=83;pD?h6;|l2437=83;pD?h6;|l2434=83;pD?h6;|l2435=83;pD?h6;|l2432=83;pD?h6;|l2433=83;pD?h6;|l2430=83;pD?h6;|l2431=83;pD?h6;|l243>=83;pD?h6;|l243?=83;pD?h6;|l243g=83;pD?h6;|l243d=83;pD?h6;|l243e=83;pD?h6;|l243b=83;pD?h6;|l243c=83;pD?h6;|l243`=83;pD?h6;|l2426=83;pD?h6;|l2427=83;pD?h6;|l2424=83;pD?h6;|l2425=83;pD?h6;|l2422=83;pD?h6;|l2423=83;pD?h6;|l2420=83;pD?h6;|l2421=83;pD?h6;|l242>=83;pD?h6;|l242?=83;pD?h6;|l242g=83;pD?h6;|l242d=83;pD?h6;|l242e=83;pD?h6;|l242b=83;pD?h6;|l242c=83;pD?h6;|l242`=83;pD?h6;|l24=6=83;pD?h6;|l24=7=83;pD?h6;|l24=4=83;pD?h6;|l24=5=83;pD?h6;|l24=2=83;pD?h6;|l24=3=83;pD?h6;|l24=0=83;pD?h6;|l24=1=83;pD?h6;|l24=>=83;pD?h6;|l24=?=83;pD?h6;|l24=g=83;pD?h6;|l24=d=83;pD?h6;|l24=e=83;pD?h6;|l24=b=83;pD?h6;|l24=c=83;pD?h6;|l24=`=83;pD?h6;|l24<6=83;pD?h6;|l24<7=83;pD?h6;|l24<4=83;pD?h6;|l24<5=83;pD?h6;|l24<2=83;pD?h6;|l24<3=83;pD?h6;|l24<0=83;pD?h6;|l24<1=83;pD?h6;|l24<>=83;pD?h6;|l24=83;pD?h6;|l24d?=83;pD?h6;|l24dg=83;pD?h6;|l24dd=83;pD?h6;|l24de=83;pD?h6;|l24db=83;pD?h6;|l24dc=83;pD?h6;|l24d`=83;pD?h6;|l24g6=83;pD?h6;|~yEFDs89>m7;9ab`65g{GHKq;qMN_{|BC \ No newline at end of file diff --git a/lib/netlists/cpu_V4.ngc b/lib/netlists/cpu_V4.ngc new file mode 100644 index 0000000..b0d6bd8 --- /dev/null +++ b/lib/netlists/cpu_V4.ngc @@ -0,0 +1,3 @@ +XILINX-XDB 0.1 STUB 0.1 ASCII +XILINX-XDM V1.4e +$7df4=7=2:;<=>6;123456789>;7=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<95?0137?567:=1;<=7;;123@1=788:?7=>=0593460339:>=95?0721?573398;<95?2011?52339>;>95?4177?534>;1;495?85A7?5>2L=1;O=6=;1G2?42<99;H=l5>2;MVPUSS2`dxxQndep?54<76=1:89:>4:36>LHW]]0JHI\N<0694;7338?1EC^ZT;CG@WD;9=0;295>6342<>7?2@D[YY4fnrvq[aoi48=1<3<41C3861=589:?7?<<239171=5?OL?7?6?0591F6553;L:>6==:HLSQQ113906?OIX\^1HDL33083:45<;;0DYY^ZT;FLE956294:?6==:NWWTPR=LFH7?<4?>59075033:3<=?5;059745633=:>995;0B27?17>9=1?8H:>1:69MKVR\3NB\L2<:1<25>2=AGZ^X7JFPC>0>58682>1EC^ZT;UFE95=87;;794FNQWW>RCE4:0;2<<44;MVPUSS2ME[M1=50?31?10>5833<>:<95:4427?0?2I=1==;767?3>4?;1=O95873@7?2B71=1136B[[PTV9|hcjWme~x1950?08;;81B71=><5>=;@17?D5F8;1J495N8G:7?D>AN=1JM5O;;@CB<1=FIHI?7LOLA39BF7=FK=1JOLO7;@FGVD:7601JHI\N<02==>GCL[K7=<06;@FGVD:6:730MIJ]A=30:g=FLMXJ0<:50?;8EABUI5;?255NDEPB848?3HNO^L2=>99B@ATF4:437LJKR@>7:==FLMXJ0807;@FGVD:1611JHI\N<6<;?DBCZH63255NDEPB8<8?3HNO^O2?>89B@ATE48:556OKDS@?548>3HNO^O2>2?;8EABUJ5;82o5NDEPA842=8730MIJ]B=37:==FLMXI0<07;@FGVG:5611JHI\M<2<;?DBCZK6?255NDEPA808?3HNO^O29>99B@ATE4>437LJKRC>;:==FLMXI040;;@D;41=E<=H97O6;;C:BE1=EJK;?7OLMD99AQVYNFOE:7N:4C1:30>E?89k0OL]LAEGJJDgB2I9>0H5>?4:F;GF26JF6:FJE969?2NBM1??>69GMD:697=0HDO313<4?AOF4895;6JFA=37:2=CAH6:9394DHC?53803MCJ0<917:FJE97?6>1OEL2>9?48@LG;97=0HDO321<4?AOF4;;5;6JFA=01:2=CAH69?394DHC?61803MCJ0?;17:FJE9416>1OEL2=7?58@LG;:14<7IGN<3;=2>BNI585;6JFA=13:<=CAH68=7>17:FJE9566?1OEL2<>79GMD:36?1OEL2:>79GMD:16?1OEL28>79GMD:?6?1OEL26>79GMG:76>1OEO2>0?58@LD;984<7IGM<00=3>BNJ5;82:5KIC>20;169GMG:607=0HDL318<5?AOE484<7IGM<32=3>BNJ58:2:5KIC>16;1>08;EKA8729?2NBN1<:>69GMG:5>7=0HDL326<4?AOE4;25;6JFB=0::3=CAK692:5KIC>04;?69GMG:497<0HDL33?48@LD;<7<0HDL35?48@LD;>7<0HDL37?48@LD;07<0HDL39?58@LVF494<7IG_A=3=3>BNXH69245KIQC?7?69?2NB\L2<>69GMUD;87=0HD^M<0<4?AOWJ58556JFPC>0>5803MC[N1=16:FLE969?2NDM1??>69GKD:697=0HBO313<4?AIF4895;6J@A=37:2=CGH6:9394DNC?53803MEJ0<917:FLE97?6>1OCL2>9?48@JG;97=0HBO321<4?AIF4;;5;6J@A=01:2=CGH69?394DNC?61803MEJ0?;17:FLE9416>1OCL2=7?58@JG;:14<7IAN<3;=2>BHI585;6J@A=13:<=CGH68=7>17:FLE9566?1OCL2<>79GKD:36?1OCL2:>79GKD:16?1OCL28>79GKD:?6?1OCL26>69GKDYUMN<0HBL30?58@JD;994<7IAM<03=3>BHJ5;92:5KOC>27;169GKG:6?7=0HBL319<4?AIE4835:6J@B=3=3>BHJ58;2:5KOC>15;1?08;EMA8759?2NDN1<;>69GKG:5=7=0HBL327<4?AIE4;=5;6J@B=0;:2=CGK695384DN@?6;14=7IAM<9<5?AIE404<7IAM_SGD3>BHXH6;2:5KOQC?5;12:2=CGYH7>374DNRA86<76>1OC]L33?18@UI23MZYM=;4DQPB50=CX[K996J_R@12?@2;86K=A@08A14CDI9>0IHH:4:GE222@2;O80J::4F@D10>@FNJ>0JLHJ5:DBHVC33OHIN95IBG;7?CEE0=1MOK6;;GAEA7=AL=1MH?><;GF@0>@CKL90JIK<;GFS7>@CZ=1MJ<>;;GD741=AN=??7KH:459EB2@33OL3<95IF@:7?C@E0=1MJOH;;GDF41=ANL2?7KHJA59EB@E33OLNJ95IFG:7?C@AM81L?6IAD09J6>O7:2C:>6G=2:K0<>OIA]ZT<=64IOKWTZ6602CEEY^P03:8MKOSXV:846GAIUR\41>:8:KMMQVX8?20ECG[P^24=>OIA]Y_MYK8;HLJPZ67?2CEEYQ?169JJLRX8;=0ECG[_114?LHN\V:?;6GAIU]312=NF@^T<;94IOKW[5103@DBXR>77:KMMQY71>1BBDZP0@58MKOSW9H<7D@FT^2@3>OIA]U;H:5FNHV\4@1169JJLRX9;=0ECG[_014?LHN\V;?;6GAIU]212=NF@^T=;94IOKW[4103@DBXR?77:KMMQY61>1BBDZP1@58MKOSW8H<7D@FT^3@3>OIA]U:H:5FNHV\5@1;94IOKW[7103@DBXR<77:KMMQY51>1BBDZP2@58MKOSW;H<7D@FT^0@3>OIA]U9H:5FNHV\6@11BBDZP3@58MKOSW:H<7D@FT^1@3>OIA]U8H:5FNHV\7@1H9;HLJPZG13@DBXRL<;HLU57=NF_OYXRMCK^FLEZTBO880ECXJRU]@HNYCGKUYIJ84J/10[I4Rh:129Nip~XzlmThd`P2^d6[5743Dg~tR|jg^fjjZ4Xn5Bmtz\v`aXl`dT>Rh:_330?HkrpVxnkRjfn^0\b0Y49:1FaxvPrde\`lhX:Vl>S9?<;Lov|ZtboVnbbR;i;Lov|ZtboVnbbR=9f:Onq}YumnUoecQ<7d9Nip~XzlmThd`P4g9Nip~XzlmThd`P40d8IhsW{olSiga_50e?HkrpVxnkRjfn^60b>Kj}qUyijQkio]70c=Je|rT~hiPdhl\00`;;O3356=I98>0BH69;>0B<:;O307<3H6;=>>7C?<4478J453><1E=>:65:L270723G;89>;4N01610=I9:?=96@>3456?K74=1?0B<=:959M56023G;8:=;4N01550=I9:<996@>3716?K74>=?0B<=9549M5601=2D:?;6:;O302<3H6;>?>7C?<7678J4501<1E=>6>5:L27=523G;848;4N01;30=I9:2296@>3836?K741:?0B<=6549M56?0=2D:?47<;O371>H6<9;>7C?;0278J427=<1E=9>84:L2043:;85A153:0>H6<;?0B<:=149M5144=2D:8?;:;O376239595A1516?K73;8?0B<:<349M5152=2D:8>9:;O377<3?=85A15601>H6<=>>7C?;4978J4228<1E=9;>5:L200423G;?9>;4N06600=I9=?>96@>4446?K73=>?0B<::849M513>=2D:8;>:;O37243=>85A15401>H6>7C?;6478J421><1E=9885:L203>23G;?:4;4N06440=I9==:96@>4606?K73?:?0B<:8449M5112=2D:8:8:;O37323<485A155:1>H6<19>7C?;8578J42?=<1E=9695:L20=123G;?44;4N06:40=I9=3:96@>4806?K731:?0B<:6449M51?2=2D:848:;O37=232485A15;:7>H6=<1E=8>?5:L215723G;>5176?K728??0B<;?749M506?=2D:9=7;;O3650=I9<;;96@>5036?K729;?0B<;>349M5073=2D:9<;:;O36533H6=83?7C?:249M5047=2D:9??:;O36673H6=;?>7C?:2978J4351<1E=8=?5:L216723G;>??;4N07070=I9<9?96@>5276?K72;??0B<;<749M505?=2D:9>7:;O36053H6?8>0B<694:L2<<29008J754:L15529:4N3627>H5=:1E>;:4N3;27>H49=1E?<>;;O1251=I;88?7C=>329M7750B>8>3:L036=I;1>0B>6>3:L0=6=I<9>0B9>>3:L756=I<;90B9=<;O677>H3>:1E9<:4N4307>H2::1E99:4N4667>H2=:1E9;=4N457?K3><=1E948;;O7:31=I>9=?7C8?829M245>:2D6@73:L;56=I0090B4?<;O;17>H><>1EIYY@RJ68JJHB92E:7]:4P@PWe>VNFVH^_DJWb:RJJZDR[GKFI>5_RD38U4=U02XJA<8W1E48VDKE9?l0^LCPEYVFJVOHFVKm7_OB_DZWAKUNGGUIo6\JAE]TMAROWHi0^HOK_VKGPMYE>2XNKNKN6:PFCFCE12Xnxb{<1<:?Wct}e~7=374Rdqvhq:5601Yi~{ct=1==>Tb{|f0906;Sgpqir;=730^h}zlu>5:<=Umzgx1919:Pfwpjs414:7^64S@TF@DRF>2YDY_MJ3:QSK2=TZ_KGSL94SSTBHZD33ZYYM95\SS@7?Q_WMj1^_H\PVHQJFIC43_IH56XFEV]W]UC33^IGG?5XE79TAD:76?1\IL2>>79TAD:5611\IL2<:1<5?RCF4:4=7ZKM<1<5?RCE484=7ZKM<3<;?RCE4:0;2;5XEC>0:g=PZ@^NSKG]SUa8SWOSMVGDHHQNc:UQMQCXEFNNSOj4WSKWAZQNL]BTMi5XRHVF[ROC\AUI=i5WIMKM\(^CJ):%=-][UC"3*4&F[JCB96V@RB[5?]USD@H<7U][_FLG3>^T\V\HO;5Wdc]J`463:47f3hf~Sb~><0a:coqZiw9585n6ocu^ms59499h1j`xQ`p0>0:g=fd|Ud|<2<>0c8eisXgy;783l4amw\ku7;<7;j7lbz_nr2808e3hf~Sb~><4<2e>gk}Ve{=181b:coqZiw95<5=l5nlt]lt4:06k1j`xQ`p0>4:4ggk}Ve{>1?12e9bhpYhx;6:2Rh:a:coqZiw:585n6ocu^ms69499k1j`xQ`p3>1:7bc9bhpYhx;6825Sk;n;`nv[jv54<4i7lbz_nr18086j2kgyRa2=7=6a=fd|Ud|?2:>^d6e>gk}Ve{>181b:coqZiw:5<5=o5nlt]lt7:16;n0ma{Poq0?2;Ya=h1j`xQ`p3>4:g=fd|Ud|?28>0`8eisXgy87;34Tj8<4cd18gimd3jgnaRokds>::f=delgThb{{<1<`?fkbeVndyy2>>b9`i`kXlf0?0l;bofiZbh}}682n5lmdo\`jss4=4h7ncjm^flqq:26j1hahcPdnww838d3jgnaRj`uu>4:2=delgT{hl4clgn[rcX[^:87n~za:asqZgd|`|n;6m}ef]ta==dzlmT{h?k;hlppZKuidUfi`k4ioqw[HtfeVgnak4ioqw[HtfeVgna9k4ioqw[HtfeVgna8k4ioqw[HtfeVgna;k4ioqw[HtfeVgna:<=;hlppZgk}&Gjhi}zb^qviZkrp9:;oi{}Uj`x!BaefpqgYt}dUfyu>?01]`}979:;1bb~zPamw,Idbc{|hTxcPmtz3456Xkp692?<4ioqw[djr'Dkoh~{m_rwn[hs89:;Snw33?01?lht|Vkgy"CndeqvfZureVg~t=>?0^az8185:2ceyQnlt-Neabt}kUxy`Qbuy2345Ydq5?5>?5fnrv\eis(EhnoxlPsto\ip~789:Tot29>308mkusWhf~#@okdrwa[vsjWds<=>?_b{?3;453`dxxRocu.Ob`aurjVy~aRczx1234Ze~4149?6gasu]bhp)JimnxyoQ|ul]nq}6789Ugyy2?>318mkusWhf~#@okdrwa[vsjWds<=>?_mww8485;2ceyQnlt-Neabt}kUxy`Qbuy2345Yk}}692?=4ioqw[djr'Dkoh~{m_rwn[hs89:;Sa{{<2<17>oi{}Uj`x!BaefpqgYt}dUfyu>?01]oqq:36;90ec}{_`nv+HgclziS~{b_lw{4567We080=3:kmwqYfd|%Fmij|uc]pqhYj}q:;<=Qcuu>5:7549?6gasu]bhp)JimnxyoQ|ul]nq}6789Ugyy27>318mkusWhf~#@okdrwa[vsjWds<=>?_ymq8485;2ceyQnlt-Neabt}kUxy`Qbuy2345Yg{692?=4ioqw[djr'Dkoh~{m_rwn[hs89:;Sua}<2<17>oi{}Uj`x!BaefpqgYt}dUfyu>?01]{kw:36;90ec}{_`nv+HgclziS~{b_lw{4567Wqey080=3:kmwqYfd|%Fmij|uc]pqhYj}q:;<=Qwos>5:7549?6gasu]bhp)JimnxyoQ|ul]nq}6789Usc27>318mkusWhf~#@okdrwa[vsjWds<=>?_ymq8<8d3`dxxRocu.L35g=nfz~Tma{ N0a8mkusWhf~#C??c:kmwqYfd|%E=oi{}Uj`x!A21f8mkusWhf~#C<>1b9jjvrXie$B?n6gasu]bhp)I>k1bb~zPamw,J2d5fnrv\eis(zlyT~hi32?30?lht|Vkgy"|js^pfc9599:1bb~zPamw,v`uXzlm783?<;hlppZgk}&xnR|jg=7=56=nfz~Tma{ rdq\v`a;>7;87d`|t^coq*tb{Vxnk191139jjvrXie$~h}Prde\4442:kmwqYfd|%yi~Q}ef]057=nfz~Tma{ rdq\v`aX<880ec}{_`nv+wctW{olS8?=;hlppZgk}&xnR|jg^426>oi{}Uj`x!}er]qabY09;1bb~zPamw,v`urd}6;2<;4ioqw[djr'{oxyaz30?31<4204\B40?=55fnrv\eis(zly~`y2?>56\WR66<2ceyQnlt-qavsk|5:598R]X0^E20>oi{}Uj`x!}erwop969>8;37d`|t^coq*tb{|f0=0Pm`r20412:kmwqYfd|%yi~{ct=3=51=nfz~Tma{ rdqvhq:668;:86gasu]bhp)umzgx1?11830?lht|Vkgy"|jstnw84839:1bb~zPamw,v`urd}6:28?;;hlppZgk}&xnxb{<0<6642>942<>oi{}Uj`x!}erwop979Wdk{=:?8;hlppZgk}&xnxb{<0<\idv5911bb~zPamw,v`urd}6:2Rcnp3223>oi{}Uj`x!}erwop979Wdk{?<94ioqw[djr'{oxyaz31?]neu36?2ceyQnlt-qavsk|5;5S`o8008mkusWhf~#k|umv?6;733`dxxRocu.pfwpjs4;4:=<:4ioqw[djr'{oxyaz32?3:56=nfz~Tma{ rdqvhq:56=;87d`|t^coq*tb{|f0?0:159jjvrXie$~h}zlu>1:046<2ceyQnlt-qavsk|585;9?;;hlppZgk}&xnxb{<3<;24>1:Zkfx;;37d`|t^coq*tb{|f0?0Pm`r14417:kmwqYfd|%yi~{ct=0=[hgw=8=0ec}{_`nv+wct}e~7>3Qbaq:26>oi{}Uj`x!}erwop9599=1bb~zPamw,v`urd}6824:kmwqYfd|%yi~{ct=1=5<743`dxxRocu.pfwpjs4:4?=>5fnrv\eis(zly~`y2<>437?lht|Vkgy"|jstnw8682:8>0ec}{_`nv+wct}e~7?39;159jjvrXie$~h}zlu>0:=0602ceyQnlt-qavsk|595S`o1634?lht|Vkgy"|jstnw868Xehz9=55fnrv\eis(zly~`y2<>^obt766?2ceyQnlt-qavsk|595S`o3058mkusWhf~#k|umv?7;Yjiy?:;6gasu]bhp)umzgx1=1_lcs<441068mkusWhf~#k|umv?0;7>9:1bb~zPamw,v`urd}6?29?<;hlppZgk}&xnxb{<5<651=nfz~Tma{ rdqvhq:36<8:86gasu]bhp)umzgx1:17537?lht|Vkgy"|jstnw818?>820ec}{_`nv+wct}e~783Qbaq3452=nfz~Tma{ rdqvhq:36Vgj|??7;hlppZgk}&xnxb{<5<\idv588=0ec}{_`nv+wct}e~783Qbaq123>oi{}Uj`x!}erwop929Wdk{9<94ioqw[djr'{oxyaz34?]neu>6:2ceyQnlt-qavsk|5?5=95fnrv\eis(zly~`y2:>0320>oi{}Uj`x!}erwop93990;87d`|t^coq*tb{|f080;129jjvrXie$~h}zlu>6:0733`dxxRocu.pfwpjs4<4>><:4ioqw[djr'{oxyaz35?5751=nfz~Tma{ rdqvhq:261<:46gasu]bhp)umzgx1;1_lcs52703`dxxRocu.pfwpjs4<4Tal~=199jjvrXie$~h}zlu>6:Zkfx;::;6gasu]bhp)umzgx1;1_lcs7417:kmwqYfd|%yi~{ct=7=[hgw0880ec}{_`nv+wct}e~7:3?;;hlppZgk}&xnxb{<7<25427;2=>5fnrv\eis(zly~`y29>530?lht|Vkgy"|jstnw83829=1bb~zPamw,v`urd}6=28<>4:kmwqYfd|%yi~{ct=4=31733`dxxRocu.pfwpjs4?43:<64ioqw[djr'{oxyaz36?]neu709>1bb~zPamw,v`urd}6=2Rcnp33;?lht|Vkgy"|jstnw838Xehz9<<94ioqw[djr'{oxyaz36?]neu56?2ceyQnlt-qavsk|5<5S`o5058mkusWhf~#k|umv?2;Yjiy2:>6gasu]bhp)umzgx191129jjvrXie$~h}zlu>4:4723`dxxRocu.pfwpjs4>4:=;?;;hlppZgk}&xnxb{<6<27439<1bb~zPamw,v`urd}6<24;>149jjvrXie$~h}zlu>4:<359>1bb~zPamw,v`urd}6<24;Pf434?lht|Vkgy"|jstnw828Xehz:=55fnrv\eis(zly~`y28>^obt44602ceyQnlt-qavsk|5=5S`o173;?lht|Vkgy"|jstnw828Xehz9;<64ioqw[djr'{oxyaz37?]neu4>911bb~zPamw,v`urd}6<2Rcnp2323>oi{}Uj`x!}erwop919Wdk{8<94ioqw[djr'{oxyaz37?]neu06?2ceyQnlt-ppdrXzlm%ol|}y048mkusWhf~#~znt^pfc+|bzf;m7d`|t^coq*usi}UyijQlaspz[hs89:;><5fnrv\eis({}kSkh_bcqv|Yj}q:;<=?>239jjvrXie$yo{_sgd[fguzpUfyu>?0132470?134\WR65>2ceyQnlt-ppdrXzlmTol|}y^ov|567888=S^Y>209jjvrXie$yo{_sgd[fguzpUfyu>?013667=nfz~Tma{ sucw[wc`Wjky~tQbuy234572>;80ec}{_`nv+vrf|VxnkRmnrs{\ip~789:9><<=;hlppZgk}&ymyQ}ef]`ewt~Wds<=>?22316>oi{}Uj`x!|t`v\v`aXkhxyuRczx1234726:81bb~zPamw,wqgsW{olSno}rx]nq}678983><5fnrv\eis({}kSkh_bcqv|Yj}q:;<=:=209jjvrXie$yo{_sgd[fguzpUfyu>?014564=nfz~Tma{ sucw[wc`Wjky~tQbuy23451>:81bb~zPamw,wqgsW{olSno}rx]nq}678928>85fnrv\eis({}kSkh_bcqv|Yj}q:;<=Qbaq3360=nfz~Tma{ sucw[wc`Wjky~tQbuy2345Yjiy;9>85fnrv\eis({}kSkh_bcqv|Yj}q:;<=Qbaq3660=nfz~Tma{ sucw[wc`Wjky~tQbuy2345Yjiy89>85fnrv\eis({}kSkh_bcqv|Yj}q:;<=Qbaq0060=nfz~Tma{ sucw[wc`Wjky~tQbuy2345Yjiy8<>95fnrv\eis({}kSkh_bcqv|Yj}q:;<=Qbaq42b>oi{}Uj`x!|t`v\v`aXkhxyuR``t123576<5fnrv\eis({}kSkh_{gqkZkrp9:;<<7>229jjvrXie$yo{_sgd[cugVg~t=>?00;\b0473`dxxRocu.qweqYumnUqiaPmtz34564<;80ec}{_`nv+vrf|VxnkRtjrn]nq}67892?=<<;;hlppZgk}&ymyQ}ef]yawiXe|r;<=>740]e172>5fnrv\eis({}kSkh_{gqkZkrp9:;oi{}Uj`x!|ul]nq}67886;2<64ioqw[djr'zfS`{w012285869>1bb~zPamw,wpkXe|r;<=<30?3;?lht|Vkgy"}zm^ov|567:5:5=<:4ioqw[djr'zfS`{w012050=nfz~Tma{ sto\ip~78999=;5fnrv\eis({|gTaxv?0111545>018mkusWhf~#~{b_sgp8786;2ceyQnlt-pqhYumz682<=4ioqw[djr'zfSk|<5<27>oi{}Uj`x!|ul]qav:26890ec}{_`nv+vsjW{ox0;0>3:kmwqYfd|%xy`Q}er>4:43oi{}Uhdd~}ef-`pwjXg|~%|lij_rgo[5473`dxxRmgiqpfc*eszeUdyy |tj]kmbnX8;:0ec}{_bjjtwc`'j~y`Razt/qwoZnnoaU:>=5fnrv\gmowzlm$oy|c_nww*vrlWacldR<=0:kmwqYd``zyij!ltsn\kpr){}aTddig_237?lht|Vice}|jg.flqq:768>0ec}{_bjjtwc`'me~x1?1159jjvrXkac{~hi dnww8786<2ceyQlhhrqab)cg|~7?3?;;hlppZeoayxnk"j`uu>7:42oi{}Uhdd~}ef-gkprX88k0ec}{_bjjtwc`'me~xR>Prrvskq743`dxxRmgiqpfc*bh}}U:=l5fnrv\gmowzlm$hb{{_0]qwqvh|890ec}{_bjjtwc`'me~xR<>3:kmwqYd``zyij!kotv\745:?6gasu]`llvumn%ocxzP5018mkusWjbb|kh/emvpZ1612ceyQlhhrqab)cg|~Tmcj?0122g>oi{}Uhdd~}ef-gkprXe|r;<=?30?3g?lht|Vice}|jg.flqqYj}q:;<<2?>03`?lht|Vice}|jg.flqqYj}q:;<<2=>0f8mkusWjbb|kh/emvpZkrp9:;=1<110a8mkusWjbb|kh/emvpZkrp9:;=1:1219jjvrXkac{~hi dnww[hs89::090PSV22g>oi{}Uhdd~}ef-gkprXe|r;<=?35?03?lht|Vice}|jg.flqqYj}q:;<<2:>^QT476?1=7=[VQ69l1bb~zPciksv`a(lfS`{w012283850;80ec}{_bjjtwc`'me~xRczx1235909:1UX[=?j;hlppZeoayxnk"j`uu]nq}67886=2>7=2:kmwqYd``zyij!kotv\ip~789;7:3Qbaq3264=nfz~Toegrde,`jssWds<=>><7<\idv?9m1bb~zPciksv`a(lfS`{w012282869l1bb~zPciksv`a(lfS`{w01228286?8n0ec}{_bjjtwc`'me~xRczx1235919?8o0ec}{_bjjtwc`'me~xRczx1235919?8897d`|t^akmutbo&ndyyQbuy2344:06>;T_Z>=1:kmwqYd``zyij!kotv\ip~789;7;3Qbaq316>oi{}Uhdd~}ef-gkprXe|r;<=?37?]neu7>:81bb~zPciksv`a(lfS`{w0122828Xehz?><5fnrv\gmowzlm$hb{{_lw{45664>4Tal~81e9jjvrXkac{~hi rde\ghcjWacld1>11e9jjvrXkac{~hi rde\ghcjWacld1?11e9jjvrXkac{~hi rde\ghcjWacld1<11e9jjvrXkac{~hi rde\ghcjWacld1=11b9jjvrXkac{~hi rde\ghcjWacldR>=3:kmwqYd``zyij!}ef]`i`kX``mcS=Q}surlp4ec:kmwqYd``zyij!}ef]`i`kX``mcS><<;hlppZeoayxnk"|jg^anahYoanbT?R||tqmw6==nfz~Toegrde,v`aXkdofSeghh^llp56798;T_Z>=8:kmwqYd``zyij!}ef]`i`kX``mcSca{012254YT_88<7d`|t^akmutbo&xnkRmbel]kmbnXff~;<=?=_RU362=nfz~Toegrde,v`aXkdofSeghh^llp5679;UX[<<8;hlppZeoayxnk"|jg^anahYoanbTbbz?0131[VQ5:>1bb~zPciksv`a(zlmTo`kb_ikdlZhh|9:;=?Q\W200?lht|Vice}|jg.pfcZoi|Vi~a jdfg\w`ht:h1bb~zPciksv`a(zlmTeczPcupo*`b`mVynb~Q}surlp761bb~zPciksv`a(zlmTeczPcupo*`hfjeoT~~zou01?lht|Vice}|jg.pfcZoi|Vi~a omcqmq512ceyQlhhrqab)umnUbbyQltsn-tjjfz`~rS}{pnv15>oi{}Uhdd~}ef-qabYnf}Uhxb!rdsvavr482ceyQlhhrqab)umnUbbyQltsn\aaabWzoeR``t12354YT_99;7d`|t^akmutbo&xnkRgat^awviYblnoTh`|_omw45669VY\=>>4ioqw[fnnx{ol#kh_hlw[frudVookhQ|eoq\jjr789;:S^Y=289jjvrXkac{~hi rde\mkrXk}xgSk~udqw[hs89:9>l5fnrv\gmowzlm$~hiPiov\gqtkW{ozyh}{_lw{45659;o0ec}{_bjjtwc`'{olSd`{_bvqhZtby|oxxRczx12364YT_98n7d`|t^akmutbo&xnkRgat^awviYumxnyQbuy23477X[^;9i6gasu]`llvumn%yijQfnu]`pwjXzl{~i~zPmtz34546WZ]9>h5fnrv\gmowzlm$~hiPiov\gqtkW{ozyh}{_lw{45659VY\??h4ioqw[fnnx{ol#kh_hlw[frudVxn}xk|t^ov|567:;;T_Z?=f:kmwqYd``zyij!}ef]jjqYd|{fT~hzerv\ip~78989=R]X23c8mkusWjbb|kh/sgd[lhsWj~y`R|jqtgppZkrp9:;>>?l;hlppZeoayxnk"|jg^rbc`Ytme6;2?10]PS5453`dxxRmgiqpfc*tboVzjkhQ|em]3[wusxf~:o6gasu]`llvumn%yijQ|tj]kmbn;87;h7d`|t^akmutbo&xnkR}{k^jjcm:668i0ec}{_bjjtwc`'{olS~zd_ikdl9499j1bb~zPciksv`a(zlmTyePhhek8686j2ceyQlhhrqab)umnUxxfQgifj\4746gasu]`llvumn%yijQ|tj]kmbnX:Vxxx}a{1c9jjvrXkac{~hi rde\wqmX``mcS><=;hlppZeoayxnk"|jg^qwoZnnoaU8S}{pnv12>oi{}Uhdd~}ef-qabYt|bUcejfPnnv34576WZ];>;5fnrv\gmowzlm$~hiPsui\llaoWge<=>>1^QT570?003\WR56<2ceyQlhhrqab)u{}Ubb{?m;hlppZeoayxnk"||t^kmr4YNF_U;>?5fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?03a8mkusWmzjxeQltsn,IwijWg:;<=Q}ol23457798;2S^Y?299jjvrXlykdRm{rm-NvjkXf9:;?113260YT_98=7d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=>>1031<>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn45679:;:><<6;hlppZbwi}bToy|c/LpliZh789:T~bc?01227474>8827d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=>>3030274e3`dxxRjauj\gqtk'DxdaR`?012\vjk789::??0^pli567889:=89=c:kmwqYcxh~cSnz}l.OqkhYi89:;Sab01235676Wdk{=><9;hlppZbwi}bToy|c/LpliZh789:T~bc?01222475i2ceyQkp`vk[frud&Gyc`Qa0123[wij89:;=;?>_RU362=nfz~Th}o{h^awvi)JzfgTb=>?0^pli5678;::=<<8;hlppZbwi}bToy|c/LpliZh789:T~bc?01214475:11bb~zPdqcwlZesze%F~bcPn1234Zthe9:;>13313>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567:9;:??64ioqw[avf|aUhxb Msmn[k6789Uyc`>?01035406:h1bb~zPdqcwlZesze%F~bcPn1234Zthe9:;>17]e17??01]qkh67898;=?0100544>9;h0ec}{_erbpmYd|{f$Aab_o2345Yugd:;<=<<100:[c3502ceyQkp`vk[frud&Gyc`Qa0123[wij89:;>>?>560`?lht|Vn{myfPcupo+HtheVd;<=>Prno34565;8;>;R]X03:8mkusWmzjxeQltsn,IwijWg:;<=Q}ol23454498n5fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?03125Zkfx8:9o6gasu]gtdroWj~y`"C}ol]m4567W{ef<=>?2232[hgw:88=7d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=>=6031e>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567:?;:S^Y?269jjvrXlykdRm{rm-NvjkXf9:;6988=7d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=><1031=>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567;8;:??011254YA:11bb~zPdqcwlZesze%F~bcPn1234Zthe9:;<>?>1^E12>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567;=;:>55fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?02625475i2ceyQkp`vk[frud&Gyc`Qa0123[wij89:;?9?>_RU36d=nfz~Th}o{h^awvi)JzfgTb=>?0^pli5678:>:=R]X1368mkusWmzjxeQltsn,IwijWg:;<=Q}ol234527:h1bb~zPdqcwlZesze%F~bcPn1234Zthe9:;<9>>_3]e171?01]qkh6789>;=R==7:kmwqYcxh~cSnz}l.OqkhYi89:;Sab0123057X<;20ec}{_erbpmYd|{f$Aab_o2345Yugd:;<=:?1^526d=nfz~Th}o{h^awvi)JzfgTb=>?0^pli5678=::S:Qi5358mkusWmzjxeQltsn,IwijWg:;<=Q}ol2345279V2996gasu]gtdroWj~y`"C}ol]m4567W{ef<=>?42310>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567<>837d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=>;70]247g?01]qkh6789><=R??_G0b?lht|Vn{myfPcupo+HtheVd;<=>Prno34563?8U:>:5fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?0552[6403`dxxRjauj\gqtk'DxdaR`?012\vjk789:?;?463\1bb~zPdqcwlZesze%F~bcPn1234Zthe9:;<99>_80:?lht|Vn{myfPcupo+HtheVd;<=>Prno34563?8U2=<9Vl>>95fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?05;10>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567=98>7d`|t^fseqnXk}xg#@|`m^l3456Xzfg;<=>:0007?lht|Vn{myfPcupo+HtheVd;<=>Prno345629;>0ec}{_erbpmYd|{f$Aab_o2345Yugd:;<=;=249jjvrXlykdRm{rm-NvjkXf9:;_3]e27g?01]qkh6789?9=R=Pf404?lht|Vn{myfPcupo+HtheVd;<=>Prno34562:8U?>l5fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?0402[1Ya=;=0ec}{_erbpmYd|{f$Aab_o2345Yugd:;<=;=1^71<>oi{}Uo|lzg_bvqh*KugdUe<=>?_smn4567=;;T9<<8;hlppZbwi}bToy|c/LpliZh789:T~bc?012664Y1:<1bb~zPdqcwlZesze%F~bcPn1234Zthe9:;<8=>249jjvrXlykdRm{rm-NvjkXf9:;279jjvrXlykdRm{rm-NvjkXf9:;:5fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?063254403`dxxRjauj\gqtk'DxdaR`?012\vjk789:<=>;5fnrv\`ugs`Vi~a!Brno\j5678Vxda=>?066257??01]qkh6789=?=13c8mkusWmzjxeQltsn,IwijWg:;<=Q}ol23451398UX[=?873\771?01]qkh67892==R:=e:kmwqYnf}Uhxb Mymq[lhsWzkf|akk_ymq4567W[oxyaz>179jjvrXag~Toy|c/hlw[del9830ec}{_hlw[frud&cexR}nmqnf`77;hlppZoi|Vi~a!fnu]ppdrbWOLo> Ga3705?lht|VcexRm{rm-jjqYt|h~nSKHk2,Km73YT_9;946gasu]jjqYd|{f$eczPsucwaZ@Al;'Bb>8PSV2\b07d3`dxxRgat^awvi)wagUxxlzj_GDg54`;hlppZoi|Vi~a!io]ppdrbWOLo> Ga_G02?lht|VcexRm{rm-smkYt|h~nSKHk2,Km[B7e3`dxxRgat^awvi)t|h~T~h}{_nww5g=nfz~TeczPcupo+vrf|VyjzhQ`uu02?lht|Vzh#@okd^tsgZgclzi<=>?_b{?4;453`dxxR~l/Lcg`ZpwkVkoh~{m0123[f;994996gasu]sg*KflmU}|nQndeqvf5678Vir0<>1_sv15>oi{}U{o"Cnde]utfYflmy~n=>?0^az8485<2ceyQc.Ob`aYqxjUjhi}zb1234Ze~484T~y<>;hlppZvd'DkohRxc^cg`vse89:;Snw32?07?lht|Vzh#@okd^tsgZgclzi<=>?_b{?6;Yu|;;0ec}{_qa,IdbcWzhSljkst`3456Xkp682?:4ioqw[ue(EhnoS{~l_`fgwpd789:Tot2<>^pw64=nfz~T|n!Baef\rueXimnxyo>?01]`}929:=1bb~zPpb-NeabX~yiTmij|uc2345Ydq5>5Sz=1:kmwqYwk&GjhiQypb]b`aurj9:;oi{}U{o"Cnde]utfYflmy~n=>?0^az808Xz}8:7d`|t^r`+HgclV|{oRokdrwa4567Wjs7:3<;;hlppZvd'DkohRxc^cg`vse89:;Snw36?]qp770ec}{_qa,IdbcWzhSljkst`3456Xkp6<2R|{209jjvrXxj%FmijPvqa\eabt}k:;<=Qly=:=61=nfz~T|n!Baef\rueXimnxyo>?01]`}9>9W{~9=6gasu]sg*KflmU}|nQndeqvf5678Vir040=4:kmwqYwk&GjhiQypb]b`aurj9:;Pxnp?5585;2ceyQc.Ob`aYqxjUjhi}zb1234Z~hz5;:2?84ioqw[ue(EhnoS{~l_`fgwpd789:Ttb|310<\vq453`dxxR~l/Lcg`ZpwkVkoh~{m0123[}iu4849>6gasu]sg*KflmU}|nQndeqvf5678Vrd~1<1239jjvrXxj%FmijPvqa\eabt}k:;<=Qwos>0:74?01]{kw:06;80ec}{_qa,IdbcWzhSljkst`3456Xpfx743<=;hlppZvd'DkohRxc^cg`vse89:;Sua}<82:kmwqYwk&zhSckwt=2=56=nfz~T|n!c^lf|q:687;87d`|t^r`+ueXflr02:440>2:kmwqYwk&zhSckwt=6=57=nfz~T|n!c^lf|q:26880ec}{_qa,tfYimq~7:3?=;hlppZvd'yiTbhv{<6<26>oi{}U{o"~l_og{p9>99;1bb~zPpb-sgZhbp}6221:kmwqYwk&zhSckwt^025>oi{}U{o"~l_og{pZ5692ceyQc.r`[kc|V>:=6gasu]sg*vdWgosxR;>1:kmwqYwk&zhSckwt^425>oi{}U{o"~l_og{pZ1692ceyQc.r`[kc|V2:=6gasu]sg*vdWgosxR7>8:kmwqYwk&zhSckwt^cm`56788;i7d`|t^r`+ueXflrSca{0122[lhqm2ceyQc.tsg969991bb~zPpb-utf:7682:<6gasu]sg*pwk5:58>h4ioqw[ue(~yi7<36>3:kmwqYwk&|{o1>1_lcs0455fnrv\tf)qxj6:<3Q\W3d8mkusWyi$z}m310<27>oi{}U{o"xc=32:ZUP8l1bb~zPpb-utf:66880ec}{_qa,rue;97UX[?k4ioqw[ue(~yi7>3?=;hlppZvd'zh0?0PSV0f?lht|Vzh#{~l<2<26>oi{}U{o"xc=1=[VQ5m2ceyQc.tsg9299;1bb~zPpb-utf:36VY\>h5fnrv\tf)qxj6>2<<4ioqw[ue(~yi793Q\W3g8mkusWyi$z}m36?31?lht|Vzh#{~l<7<\WR4b3`dxxR~l/wr`8286:2ceyQc.tsg919WZ]9i6gasu]sg*pwk525=?5fnrv\tf)qxj632R]X2d9jjvrXxj%}|n26>008mkusWyi$z}m39?]PS77f3`dxxR~l/wr`[dbc{|h;<=>311<2e>oi{}U{o"xc^cg`vse89:;0?0=1=5<=nfz~T|n!ypb]b`aurj9:;<1:1189jjvrXxj%}|nQndeqvf56785?5=45fnrv\tf)qxjUjhi}zb1234909901bb~zPpb-utfYflmy~n=>?0=5=5<=nfz~T|n!ypb]b`aurj9:;<161189jjvrXxj%}|nQndeqvf5678535=<5fnrv\tf)qxjUyijQ?109jjvrXxj%}|nQ}ef]257=nfz~T|n!ypb]qabY68880ec}{_qa,rueXzlmT=;hlppZvd'zhSkh_332?lht|Vzh#{~l_sgd[6763`dxxR~l/wr`[wc`W=;:7d`|t^r`+svdW{olS8?>;hlppZvd'zhSkh_732?lht|Vzh#{~l_sgd[2763`dxxR~l/wr`[wc`W1;:7d`|t^r`+svdW{olS4?9;hlppZvd'zhSkh_np34566?2ceyQc.tsgZtboVey<=>?1328mkusWz~jofQltsn,Ifirf}U{xQly=2=65=nfz~Tyolk^awvi)JkfexR~{r^az848582ceyQ|t`ah[frud&Ghcx`{_qvq[f;:78;7d`|t^qwefmXk}xg#@m`uov\tqtXkp682?>4ioqw[vrfkbUhxb MbmvjqYw|{Uhu1:1219jjvrX{}khgRm{rm-Ngjsi|Vz~Rmv<4<14>oi{}Uxxlmd_bvqh*Kdg|dS}z}_b{?2;473`dxxR}{abi\gqtk'DidyczPpup\g|:06;;0ec}{_rvbgnYd|{f$Anaznu]spwYk}}6;2??4ioqw[vrfkbUhxb MbmvjqYw|{Ugyy2>>338mkusWz~jofQltsn,Ifirf}U{xQcuu>1:77338mkusWz~jofQltsn,Ifirf}U{xQcuu>5:77338mkusWz~jofQltsn,Ifirf}U{xQwos>2:77338mkusWz~jofQltsn,Ifirf}U{xQwos>6:77058mkusWz~jofQltsn,`jss494:46gasu]ppdelWj~y`"j`uu>24;7?3`dxxR}{abi\gqtk'me~x1?>>058mkusWz~jofQltsn,`jss484:;6gasu]ppdelWj~y`"j`uu>1:410>7:kmwqYt|hi`Snz}l.flqq:368=0ec}{_rvbgnYd|{f$hb{{<4<23>oi{}Uxxlmd_bvqh*bh}}6=2<94ioqw[vrfkbUhxb dnww8286?2ceyQ|t`ah[frud&ndyy27>058mkusWz~jofQltsn,`jss404::6gasu]ppdelWj~y`"j`uu]353=nfz~Tyolk^awvi)cg|~T=<94ioqw[vrfkbUhxb dnww[466?2ceyQ|t`ah[frud&ndyyQ>1048mkusWz~jofQltsn,`jssW;;=7d`|t^qwefmXk}xg#iazt^122>oi{}Uxxlmd_bvqh*bh}}U?=;5fnrv\wqgdcVi~a!kotv\1402ceyQ|t`ah[frud&ndyyQ7179jjvrX{}khgRm{rm-gkprX18<0ec}{_rvbgnYd|{f$ahcPwd35?lht|VymnePcupo+uru494::6gasu]ppdelWj~y`"~{r=3=53=nfz~Tyolk^awvi)w|{692<84ioqw[vrfkbUhxb pup?7;713`dxxR}{abi\gqtk'y~y090>6:kmwqYt|hi`Snz}l.rwv9399?1bb~zPsuc`oZesze%{x29>048mkusWz~jofQltsn,tqt;?7;=7d`|t^qwefmXk}xg#}z}<9<21>oi{}Uxxlmd_bvqh*vszV::96gasu]ppdelWj~y`"~{r^321>oi{}Uxxlmd_bvqh*vszV8:96gasu]ppdelWj~y`"~{r^121>oi{}Uxxlmd_bvqh*vszV>:96gasu]ppdelWj~y`"~{r^721>oi{}Uxxlmd_bvqh*vszV<:96gasu]ppdelWj~y`"~{r^521>oi{}Uxxlmd_bvqh*vszV2:n6gasu]ppdelWj~y`"~{r^llp56798n0ec}{_rvbgnYd|{f$|y|Pnnv3457698i0ec}{_rvbgnYd|{f$|y|Pnnv345759l1bb~zPsuc`oZesze%{xQaou23444698o0ec}{_rvbgnYd|{f$|y|Pnnv34575WO;n7d`|t^qwefmXk}xg#}z}_omw4566:VM:h6gasu]ppdelWj~y`"~{r^llp5679:;:h6gasu]ppdelWj~y`"~{r^llp5679<;:j6gasu]ppdelWj~y`"~{r^llp5679VY\oi{}xThd`3111?f8mkuszVnbb1?=>e9jjvruWmce0<=1d:kmwqtXl`d7=90k;hlppwYcag6:93j4ioqwvZbnf5;=2k5fnrvq[aoi48=1<3j4ioqwvZbnf5;<2h5fnrvq[aoi48=5=k5fnrvq[aoi48=5=_RU357=nfz~ySiga<05=5ZUP:880ec}{r^fjj97068UX[>??;hlppwYcag6:;3<>1g9jjvruWmce0<91_Gd8mkuszVnbb1?8>^E`?lht|{Uoec2>>b9jjvruWmce0?0l;hlppwYcag682n5fnrvq[aoi4=4h7d`|ts]gmk:26j1bb~z}_ekm838d3`dxxQkio>4:f=nfz~ySiga<9<`?lht|{Uoec26>69jjqYfkb<0eczPio`8mkrX{}aT|b~l;hlw[vrlWyxd;5fo^qfh<=nxakxi1>18:ksldubW9;;7d~garg\4Zkrp9:;<<94iqjbw`Y7Wds<=>?1^KMRZ6e3dofSljkr=2=b>kbeVkoh2?>^QT4c=jmdUjhi|30?]PS4dkbeVkoh2=>e9nahYflmx7>3Q>f:ofiZgcl{692R]X0g9nahYflmx7>3Q\W0a8i`kXimny0>0>c:ofiZgcl{682?k4mdo\eabu4:4Tj8l4mdo\eabu4=4m7`kb_`fgv929WZ];j6cjm^cg`w:36VY\=n5bel]b`at;=7;h7`kb_`fgv939:l1fi`Qndep?1;Ya=j1fi`Qndep?2;7d3dofSljkr=4=6`=jmdUjhi|36?]e1f=jmdUjhi|37?3`?hcjWhno~1912d9nahYflmx7;3Qi5b9nahYci}k7<3?l;lgn[agsi5;5=n5bel]geqg;:7;h7`kb_ecwe9599j1fi`Qkauc?0;7d3dofSio{a=7=5f=jmdUomyo36?3`?hcjWmkm1911`9sgZoi494:=o5c^km846998=0|nQco`f;?ueXdfko=i5}ef]b[air|5:5h6|jg^c\`jss484o7kh_`]gkpr;:7n0~hiPa^flqq:46m1yijQn_emvp929l2xnkRoPdnww808c3{olSlQkotv?2;b4:a=umnUiSiazt=2=`>tboVhThb{{<0e9qabYeWme~x1:1d:pfcZdXlf080k;sgd[gYcg|~7:3j4rde\fZbh}}6<2l5}ef]gmk:76h1yijQkio>2:d=umnUoec2=>`9qabYcag682l5}ef]gmk:36h1yijQkio>6:d=umnUoec29>`9qabYcag6<2<<4rde\`lhXe|r;<=>30?30?wc`WmceS`{w012385869>1yijQkio]nq}67896;2?=;sgd[aoiWds<=>?<0<27>tboVnbbRczx12349799880~hiPdhl\ip~789:7>3?<;sgd[aoiWds<=>?<3<257=umnUoecQbuy2345:46890~hiPdhl\ip~789:7?3?>2:pfcZbnfVg~t=>?0=6=56=umnUoecQbuy2345:368;97kh_ekm[hs89:;080>3:pfcZbnfVg~t=>?0=7=5447;87kh_ekm[hs89:;0;0>139qabYcagUfyu>?01>4:45131]E`>uscVce0=0<0^Eb?vrlW`d7<38j;rvh[lh;87Ufm}=j;rvh[lh;87Ufm};n;rvh[lh;994i7~zd_hl?5586l2ygRga<02=[c3f3z~`Sd`310d:qwoZoi48;5Sk;6;rvh[lh;97h0yePio>2:66c3z~`Sd`31?13[Cb<{}aTec2>>22\Cd=t|bUbb1?16d9ppnYnf5;5S`o389ppnYnf585n6}{k^km87848m1xxfQfn=0=75YAl2ygRga<3<04ZAf3z~`Sd`32?4f?vrlW`d7>3Qbaq1:?vrlW`d7?3l4sui\mk:46::o7~zd_hl?7;57WOn0yePio>0:66XOh1xxfQfn=1=2`=t|bUbb1=1_lcs7<=t|bUbb1:1b:qwoZoi4=483z~`Sd`35?`8wqmXag6>2>>k;rvh[lh;=79;SKj4sui\mk:26::TKl5|tj]jj939>l1xxfQfn=7=[hgw;01xxfQfn=4=f>uscVce0;0<0e9ppnYnf5<5?=QId:qwoZoi4?48722g?vrlW`d7;3=?_Gf8wqmXag6<2>>PG`9ppnYnf5=5:l5|tj]jj9191l1xxfQfn=5=[hgw;01xxfQfn=:=e>uscVce050>c:qwoZoi414Tj874sui\mk:>6h1xxfQfn=;=5f=t|bUbb171_g7f?vrlW`dTmcj?012e?vrlW`dTmcj?0122e>uscVe~x1>1b:qwoZir|5;;2o5|tj]lqq:697k0yePotv?5;g<{}aTcxz32?c8wqmXg|~7?3o4sui\kpr;<7k0yePotv?1;g<{}aTcxz36?c8wqmXg|~7;3o4sui\kpr;07k0yePotv?=;><{}aT|x}ga:qwoZvr{a;:56}{k^rvwm4f3z~`S}{|h33;?rgtWyighl5xar]sku4wk8;0tn:ysy16)46*no<=4<<4xhm\w`jXkdzTi|>?0135?}ohWzogSnc_ds3456X[^:h7ucjm^cg`w:76j1sahcPaefq848d3qgnaRokds>1:f=elgTmij}<2<`?}kbeVkoh2;>b9{i`kXimny080l;yofiZgcl{6=2h5wmdo\eabu4>0;2n5wmdo\eabu4>4i7ucjm^fjj969j2rfi`Qkio>2:g=elgThd`32?`8|hcjWmce0>0m;yofiZbnf5>5n6vbel]gmk:26k1sahcPdhl?2;b1c:znahYcg|~7=3m4xlgn[air|585o6vbel]gkpr;;7i0t`kb_emvp929k2rfi`Qkotv?1;e~jmdUocxz37;2=g>~jmdUocxz37?58|hcjW{oi7ucjm^pf[VQ712rfi`Qxahv4?}kbeV}nqMN150f?EF;>91J7<51zQb5?54<3;o?7?<274b`?7>>8==:09m765=<2.8?<4<2b9~Wd6=;:>1=i=512052db=90<4<6sZk:6>=;:0f0>455>?ko6<794b9uP676290:6<4=c3yPe4<4;=0:h>4>3345ea<61?>h7)=>a;3g2>"5n10=hn5m36194?5a2;=i6?m={I12<>"49>08;>5U8g8606=3:17d877;29?j0ai3:17b8<1;29?j0al3:17d8ic;29?l05m3:17b8i9;29 7`f2?l37c3:1(?hn:724?k4a13;07b8>1;29 7`f2?:<7cb;29 7`f2?;j7c8;29 7`f2?;j7c6;29 7`f2?;j7c4;29 7`f2?;j7co19;0;6)h5n00:=65f6g294?"5nh0=ik5a2g;94>=n>lo1<7*=f`85ac=i:o31=65f6df94?"5nh0=ik5a2g;96>=n>li1<7*=f`85ac=i:o31?65f6d`94?"5nh0=ik5a2g;90>=n>lk1<7*=f`85ac=i:o31965f6d;94?"5nh0=ik5a2g;92>=n>l21<7*=f`85ac=i:o31;65m32294?7=83:p(>?8:23:?M55m2B8=55`2g594?=zj:8m6=4>:183!56?3;?7;%3;`?6>o>n3:17do=:188k7`d2900qo=84;290?6=8r.8=:4>689K77c<@:;37d7?:188m<`=831bm?4?::m1bf<722wi:5650;694?6|,:;<6<8m;I11a>N4911b5=4?::k:=?6=3`k96=44o3d`>5<54;294~"49>0::o5G33g8L67?3`3;6=44i8;94?=ni;0;66a=fb83>>{e=l31<7:50;2x 67028<27E==e:J05==n190;66g6f;29?lg52900c?hl:188yg3b83:197>50z&052<6>h1C??k4H23;?l?72900e4750;9j=c<722cj>7>5;n0eg?6=3th>hk4?:483>5}#;8=1=;o4H20f?M5602c2<7>5;h;:>5<>i5nj0;66sm5d:94?3=83:p(>?8:04b?M55m2B8=55f9183>>o>13:17d7i:188md4=831d>km50;9~f0c0290>6=4?{%123?71i2B8>h5G30:8m<6=831b544?::k:b?6=3`k96=44o3d`>5<55;294~"49>0::l5G33g8L67?3`3;6=44i8;94?=n1o0;66gn2;29?j4ak3:17pl:e483>0<729q/?<9517c8L64b3A9:46g60;29?l?>2900e4h50;9je7<722e9jn4?::a1`2=83?1<7>t$234>40f3A99i6F<199j=5<722c257>5;h;e>5<>o>n3:17do=:188k7`d2900qo;j2;291?6=8r.8=:4>6`9K77c<@:;37d7?:188m5;|`6a4<72<0;6=u+305953g<@:8n7E=>8:k:4?6=3`326=44i8d94?=ni;0;66a=fb83>>{e=mo1<7;50;2x 670285<7s-9:;7?9a:J06`=O;820e4>50;9j=<<722c2j7>5;hc1>5<?7;h;3>5<86=4<:183!56?3;=;6F<2d9K74>>i5nj0;66sm55694?5=83:p(>?8:044?M55m2B8=55f9183>>of:3:17b"60m0;7d7?:188m<`=831bm?4?::m1bf<722wi9>m50;694?6|,:;<6<86;I11a>N4911/=5j50:k:4?6=3`3m6=44i`094?=h:oi1<75rb414>5<3290;w)=>7;35=>N4:l1C?<64$0:g>5=n190;66g6f;29?lg52900c?hl:188yg34<3:187>50z&052<6>01C??k4H23;?!7?l3:0e4>50;9j=c<722cj>7>5;n0eg?6=3th?:;4?:b094?6|,:;<6?hi;I11a>N4911Q4k4l{0f95`<5i38i6>8536802;i1>i4x"60k087)?7c;18 64?2:8<7)==9;113>h48;0:>6`<02826>h4:h0:>6`<2c826>h69<0;7c?<7;28 67728<:7)=?1;0e1>"49:0:7)?7e;18 4>a2:1/=4>53:&2=4<43-;2>7=4$0;0>6=#90>1?6*>9480?!7>>390(<78:29'5<>=;2.:544<;%3:e?5<,83i6>5+18a97>"61m087)?6e;18 4?a2:1/=l>53:&2e4<43-;j>7=4$0c0>6=#9h>1?6*>a480?!7f>390(=;2.:m44<;%3be?5<,8ki6>5+1`a97>"6im087)?ne;18 4ga2:1/=o>53:&2f4<43-;i>7=4$0`0>6=#9k>1?6*>b480?!7e>390(=;2.:n44<;%3ae?5<,8hi6>5+1ca97>"6jm087)?me;18 4da2:1/=n>53:&2g4<43-;h>7=4$0a0>6=#9j>1?6*>c480?!7d>390(=;2.:o44<;%3`e?5<,8ii6>5+1ba97>"6km087)?le;08 4ea2;1/=5;53:&2<3<43-;3;7=4$0:;>6=#9131?6*>8`80?!7c93;==6*>d38224=#;9:1>k;4$237>4=n1:0;66g64;29?l?c2900e4k50;9j505=831b?=:50;9j753=831b=8:50;9j743=831b?<850;9l=0<722e2:7>5;h4e>5<#:ok1:h5a2g;94>=n>m0;6)l1e>k752:9j2g<72-8mm78j;o0e=?5<3`!4ai3ko56d9m6c?=>21b;;4?:%0ee?0b3g8m5794;h56>5<#:ok1:h5a2g;9<>=n?=0;6)l1e>k75a:9j37<72-8mm78j;o0e=?d<3`=:6=4+2gc92`=i:o31o65f7183>!4ai3290/>ko56d9m6c?=m21b;k4?:%0ee?1b3g8m57>4;h5g>5<#:ok1;h5a2g;95>=n?j0;6)k753:9j3d<72-8mm79j;o0e=?2<3`236=4+2gc93`=i:o31965f8683>!4ai3=n7c1290/>ko57d9m6c?=?21b484?:%0ee?1b3g8m5764;h:7>5<#:ok1;h5a2g;9=>=n0:0;6)k75b:9j<4<72-8mm79j;o0e=?e<3`2;6=4+2gc93`=i:o31h65f7883>!4ai3=n7cko5c19m6c?=821bnk4?:%0ee?e73g8m57?4;h`g>5<#:ok1o=5a2g;96>=njj0;6)k754:9jfd<72-8mm7m?;o0e=?3<3`h26=4+2gc9g5=i:o31:65fb983>!4ai3i;7cko5c19m6c?=021bn;4?:%0ee?e73g8m5774;h`6>5<#:ok1o=5a2g;9e>=nj=0;6)k75c:9jf4<72-8mm7m?;o0e=?b<3`h;6=4+2gc9g5=i:o31i65fag83>!4ai3i;7cko5c19m6c?=9910elj50;&1bd1:9jef<72-8mm7m?;o0e=?7532cjn7>5$3db>f65<#:ok1o=5a2g;951=h5n00:965fc983>!4ai3i;7cod?3:1(?hn:b28j7`>28=07dm9:18'6cg=k91e>k751998mf3=83.9jl4l0:l1b<<6121bo94?:%0ee?e73g8m57?n;:k`7?6=,;lj6n>4n3d:>4d<3`i96=4+2gc9g5=i:o31=n54icg94?"5nh0h<6`=f882`>=nj:0;6)ko5e09m6c?=821bi=4?:%0ee?c63g8m57?4;hff>5<#:ok1i<5a2g;96>=nlm0;6)k754:9j`g<72-8mm7k>;o0e=?3<3`nj6=4+2gc9a4=i:o31:65fd883>!4ai3o:7cko5e09m6c?=021bh:4?:%0ee?c63g8m5774;hf5>5<#:ok1i<5a2g;9e>=nl<0;6)k75c:9j`7<72-8mm7k>;o0e=?b<3`n:6=4+2gc9a4=i:o31i65fd183>!4ai3o:7cko5e09m6c?=9910enk50;&1bd1:9jga<72-8mm7k>;o0e=?7532cho7>5$3db>`75<#:ok1i<5a2g;951=h5n00:965fe883>!4ai3o:7cob03:1(?hn:d38j7`>28=07dk8:18'6cg=m81e>k751998m`0=83.9jl4j1:l1b<<6121bi84?:%0ee?c63g8m57?n;:kf0?6=,;lj6h?4n3d:>4d<3`o86=4+2gc9a4=i:o31=n54ied94?"5nh0n=6`=f882`>=nl=0;6)ko5ee9m6c?=821bin4?:%0ee?cc3g8m57?4;hga>5<#:ok1ii5a2g;96>=nmh0;6)k750:9jb4<72-8mm7h=;o0e=?7<3`l;6=4+2gc9b7=i:o31>65feg83>!4ai3l97cf;29 7`f2:8;7cd;29 7`f2:8;7c3:1(?hn:206?k4a13:07d==4;29 7`f2:8>7c7c07b??6;29 7`f28:h7cko511a8j7`>2j10ckj50;&1bd<68j1e>k75d:9lbf<72-8mm7??c:l1b<5$3db>46d3g8m57h4;ndb>5<#:ok1==m4n3d:>46<3fl26=4+2gc955e5<#:ok1==m4n3d:>44<3fl<6=4+2gc955e5<#:ok1==m4n3d:>42<3fl>6=4+2gc955el;o0e=?7132e:=>4?:%0ee?77k2d9j44>7:9l544=83.9jl4>0b9m6c?=9110c:18'6cg=99i0b?h6:0;8?j7683:1(?hn:02`?k4a13;j76a>0g83>!4ai3;;o6`=f882f>=h99o1<7*=f`824f=i:o31=n54o02b>5<#:ok1==m4n3d:>4b<3flm6=4+2gc955e5<#:ok1==m4n3d:>4`<3f;9j7>5$3db>44b3g8m57>4;n31`?6=,;lj6<5$3db>44b3g8m57<4;n31e?6=,;lj6<5$3db>44b3g8m57:4;n315$3db>44b3g8m5784;n312?6=,;lj6<5$3db>44b3g8m5764;n310?6=,;lj6<5$3db>44b3g8m57o4;n316?6=,;lj6<5$3db>44b3g8m57m4;n32b?6=,;lj6<5$3db>44b3g8m57k4;n32`?6=,;lj6<5$3db>44b3g8m57??;:m25g<72-8mm7?=e:l1b<<6921d=k751398k47>290/>ko513g8j7`>28907b?>8;29 7`f288n7ci69>0;6)h5n00:965`12494?"5nh0:>h5a2g;953=6=4+2gc957c4?:%0ee?75m2d9j44>9:9l564=83.9jl4>2d9m6c?=9h10c<=>:18'6cg=9;o0b?h6:0`8?j7483:1(?hn:00f?k4a13;h76a>2b83>!4ai3;9i6`=f882`>=h9;;1<7*=f`826`=i:o31=h54o035>5<#:ok1=?k4n3d:>4`<3f;8o7>5$3db>45e3g8m57>4;n30e?6=,;lj6<=m;o0e=?7<3f;857>5$3db>45e3g8m57<4;n305$3db>4273g8m57>4;n30b?6=,;lj6<:?;o0e=?7<3f;8i7>5$3db>4273g8m57<4;n30`?6=,;lj6<:?;o0e=?5<3th8;:4?:e83>5}#;8=1>kk4H20f?M5602c>57>5;h7b>5<>of:3:17d?;3;29?l73<3:17d?;5;29?l73>3:17d=>b;29?l56k3:17b=>2;29?j73:3:17pl<7983>a<729q/?<952gg8L64b3A9:46g:9;29?l3f2900e8l50;9j1a<722cj>7>5;h377?6=3`;?87>5;h371?6=3`;?:7>5;h12f?6=3`9:o7>5;n126?6=3f;?>7>5;|`03<<72m0;6=u+30596cc<@:8n7E=>8:k6=?6=3`?j6=44i4`94?=n=m0;66gn2;29?l73;3:17d?;4;29?l73=3:17d?;6;29?l56j3:17d=>c;29?j56:3:17b?;2;29?xd4?j0;6i4?:1y'741=:oo0D>o213:17d;n:188m0d=831b9i4?::kb6?6=3`;??7>5;h370?6=3`;?97>5;h372?6=3`9:n7>5;h12g?6=3f9:>7>5;n376?6=3th8;l4?:e83>5}#;8=1>kk4H20f?M5602c>57>5;h7b>5<>of:3:17d?;3;29?l73<3:17d?;5;29?l73>3:17d=>b;29?l56k3:17b=>2;29?j73:3:17pl<7c83>a<729q/?<952gg8L64b3A9:46g:9;29?l3f2900e8l50;9j1a<722cj>7>5;h377?6=3`;?87>5;h371?6=3`;?:7>5;h12f?6=3`9:o7>5;n126?6=3f;?>7>5;|`03a<72m0;6=u+30596cc<@:8n7E=>8:k6=?6=3`?j6=44i4`94?=n=m0;66gn2;29?l73;3:17d?;4;29?l73=3:17d?;6;29?l56j3:17d=>c;29?j56:3:17b?;2;29?xd4?l0;6i4?:1y'741=:oo0D>o213:17d;n:188m0d=831b9i4?::kb6?6=3`;??7>5;h370?6=3`;?97>5;h372?6=3`9:n7>5;h12g?6=3f9:>7>5;n376?6=3th>j>4?:483>5}#;8=1=;o4H20f?M5602c2<7>5;h;:>5<>i5nj0;66sm5g694?3=83:p(>?8:04b?M55m2B8=55f9183>>o>13:17d7i:188md4=831d>km50;9~f0`2290>6=4?{%123?71i2B8>h5G30:8m<6=831b544?::k:b?6=3`k96=44o3d`>5<55;294~"49>0::l5G33g8L67?3`3;6=44i8;94?=n1o0;66gn2;29?j4ak3:17pl:f683>0<729q/?<9517c8L64b3A9:46g60;29?l?>2900e4h50;9je7<722e9jn4?::a1c>=83?1<7>t$234>40f3A99i6F<199j=5<722c257>5;h;e>5<>o>n3:17do=:188k7`d2900qo;ia;291?6=8r.8=:4>6`9K77c<@:;37d7?:188m5;|`6bg<72<0;6=u+305953g<@:8n7E=>8:k:4?6=3`326=44i8d94?=ni;0;66a=fb83>>{e=k=1<7:50;2x 67028o;7E==e:J05==n1j0;66gn7;29?l57n3:17b4?:1y'741=;;n0D>o>k3:17d?k4;29?j4a>3:17pl:b983>1<729q/?<951d28L64b3A9:46g6c;29?lg02900e>>i:188k7`12900qo;l9;297?6=8r.8=:4<2e9K77c<@:;37d7l:188m4b32900c?h9:188yg3e13:187>50z&052<6m91C??k4H23;?l?d2900el950;9j75`=831d>k850;9~f0ef29086=4?{%123?55l2B8>h5G30:8m5<7s-9:;7?j0:J06`=O;820e4m50;9je2<722c8N4911b5n4?::k2`1<722e9j;4?::a1gd=83>1<7>t$234>4c73A99i6F<199j=f<722cj;7>5;h13b?6=3f8m:7>5;|`6gf<72:0;6=u+305977b<@:8n7E=>8:k:g?6=3`;o87>5;n0e2?6=3th>nn4?:583>5}#;8=1=h>4H20f?M5602c2o7>5;hc4>5<5<53;294~"49>08>i5G33g8L67?3`3h6=44i0f7>5<?7;h;`>5<5<4290;w)=>7;11`>N4:l1C?<64i8a94?=n9m>1<75`2g494?=zj>o48o0;66a=f783>>{e=jl1<7=50;2x 6702:8o7E==e:J05==n1j0;66g>d583>>i5n?0;66sm5e294?5=83:p(>?8:20g?M55m2B8=55f9b83>>o6l=0;66a=f783>>{e9lk1<7:50;2x 67028o:7E==e:J05==n91;1<75f19094?=n;9l1<75`2g494?=zj8lj6=4;:183!56?3;om6F<2d9K74><,82o6<:n;h3;5?6=3`;3>7>5;h3;7?6=3f8m:7>5;|`2b7<72=0;6=u+30595ag<@:8n7E=>8:&24?::m1b3<722wi=h750;694?6|,:;<6;I11a>N4911b=5?50;9j5=4=831b?=h50;9l6c0=831vn5<7s-9:;7?ka:J06`=O;820(<6k:06b?l7?93:17d?72;29?l7?;3:17b"60m03n6g>8083>>o60;0;66g>8283>>i5n?0;66sm1d:94?2=83:p(>?8:0g2?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb0d;>5<3290;w)=>7;3ge>N4:l1C?<64$0:g>42f3`;3=7>5;h3;6?6=3`;3?7>5;n0e2?6=3th:j=4?:583>5}#;8=1=io4H20f?M5602.:4i47b:k2<4<722c:4?4?::k2<6<722e9j;4?::a5`1=83>1<7>t$234>4c63A99i6F<199j5=7=831b=5<50;9j75`=831d>k850;9~f4`0290?6=4?{%123?7ci2B8>h5G30:8 4>c28>j7d?71;29?l7?:3:17d?73;29?j4a>3:17pl>eg83>1<729q/?<951ec8L64b3A9:46*>8e8;f>o6080;66g>8383>>o60:0;66a=f783>>{e9l<1<7:50;2x 67028o:7E==e:J05==n91;1<75f19094?=n;9l1<75`2g494?=zj8l=6=4;:183!56?3;om6F<2d9K74><,82o6<:n;h3;5?6=3`;3>7>5;h3;7?6=3f8m:7>5;|`2a`<72=0;6=u+30595ag<@:8n7E=>8:&24?::m1b3<722wi=h;50;694?6|,:;<6;I11a>N4911b=5?50;9j5=4=831b?=h50;9l6c0=831vn5<7s-9:;7?ka:J06`=O;820(<6k:06b?l7?93:17d?72;29?l7?;3:17b"60m03n6g>8083>>o60;0;66g>8283>>i5n?0;66sm1d694?2=83:p(>?8:0g2?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb0d7>5<3290;w)=>7;3ge>N4:l1C?<64$0:g>42f3`;3=7>5;h3;6?6=3`;3?7>5;n0e2?6=3th:in4?:583>5}#;8=1=io4H20f?M5602.:4i47b:k2<4<722c:4?4?::k2<6<722e9j;4?::a5`5=83>1<7>t$234>4c63A99i6F<199j5=7=831b=5<50;9j75`=831d>k850;9~f4`4290?6=4?{%123?7ci2B8>h5G30:8 4>c28>j7d?71;29?l7?:3:17d?73;29?j4a>3:17pl>ec83>1<729q/?<951ec8L64b3A9:46*>8e8;f>o6080;66g>8383>>o60:0;66a=f783>>{e=9:1<7:50;2x 67028o:7E==e:J05==n91;1<75f19094?=n;9l1<75`2g494?=zj<::6=4::183!56?3;oh6F<2d9K74><,82o6<9:;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th>5}#;8=1=h?4H20f?M5602c:4<4?::k2<7<722c8N4911/=5j515:8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;?c;291?6=8r.8=:4>de9K77c<@:;37)?7d;37<>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm50;94?2=83:p(>?8:0g1?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb43`>5<3290;w)=>7;3f5>N4:l1C?<64i0:2>5<5<?7;%3;`?70:2c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a14c=83?1<7>t$234>4bc3A99i6F<199'5=b=9>80e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg36i3:187>50z&052<6m81C??k4H23;?l7?93:17d?72;29?l57n3:17b"60m0:;?5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj<;i6=4::183!56?3;oh6F<2d9K74><,82o6<9=;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th>>i4?:583>5}#;8=1=h?4H20f?M5602c:4<4?::k2<7<722c8N4911/=5j51558m4>62900e<6=:188k7`12900qo;:c;297?6=8r.8=:4<2e9K77c<@:;37d7l:188m4b32900c?h9:188yg32j3:1?7>50z&052<4:m1C??k4H23;?l?d2900ee19K77c<@:;37d7l:188md1=831b?=h50;9l6c0=831vn889:180>5<7s-9:;7==d:J06`=O;820e4m50;9j5a2=831d>k850;9~f03?290?6=4?{%123?7b82B8>h5G30:8mt$234>64c3A99i6F<199j=f<722c:h94?::m1b3<722wi98850;694?6|,:;<6N4911b5n4?::kb3?6=3`9;j7>5;n0e2?6=3th>:94?:283>5}#;8=1??j4H20f?M5602c2o7>5;h3g0?6=3f8m:7>5;|`611<72=0;6=u+30595`6<@:8n7E=>8:k:g?6=3`k<6=44i22e>5<?7;h;`>5<5<>7>54;294~"49>0:i=5G33g8L67?3`3h6=44i`594?=n;9l1<75`2g494?=zj<<96=4<:183!56?399h6F<2d9K74>5<3290;w)=>7;3f4>N4:l1C?<64i8a94?=ni>0;66g<0g83>>i5n?0;66sm57394?5=83:p(>?8:20g?M55m2B8=55f9b83>>o6l=0;66a=f783>>{e==o1<7:50;2x 67028o;7E==e:J05==n1j0;66gn7;29?l57n3:17b90;6>4?:1y'741=;;n0D>o>k3:17d?k4;29?j4a>3:17pl:4b83>1<729q/?<951d28L64b3A9:46g6c;29?lg02900e>>i:188k7`12900qo;:f;297?6=8r.8=:4<2e9K77c<@:;37d7l:188m4b32900c?h9:188yg33i3:187>50z&052<6m91C??k4H23;?l?d2900el950;9j75`=831d>k850;9~f03b29086=4?{%123?55l2B8>h5G30:8m5<7s-9:;7?j0:J06`=O;820e4m50;9je2<722c8N4911b5n4?::kb3?6=3`9;j7>5;n0e2?6=3th>mn4?:483>5}#;8=1=;o4H20f?M5602c2<7>5;h;:>5<>i5nj0;66sm5``94?3=83:p(>?8:04b?M55m2B8=55f9183>>o>13:17d7i:188md4=831d>km50;9~f0d3290>6=4?{%123?71i2B8>h5G30:8m<6=831b544?::k:b?6=3`k96=44o3d`>5<55;294~"49>0::l5G33g8L67?3`3;6=44i8;94?=n1o0;66gn2;29?j4ak3:17pl:b383>0<729q/?<9517c8L64b3A9:46g60;29?l?>2900e4h50;9je7<722e9jn4?::a1g7=83?1<7>t$234>40f3A99i6F<199j=5<722c257>5;h;e>5<>o>n3:17do=:188k7`d2900qo;nf;291?6=8r.8=:4>6`9K77c<@:;37d7?:188m5;|`6e`<72<0;6=u+305953g<@:8n7E=>8:k:4?6=3`326=44i8d94?=ni;0;66a=fb83>>{e=hn1<7;50;2x 670285<7s-9:;7?9a:J06`=O;820e4>50;9j=<<722c2j7>5;hc1>5<?7;h;3>5<>of:3:17b0;694?:1y'741=9?h0D>o>83:17d76:188md4=831d>km50;9~f011290?6=4?{%123?71j2B8>h5G30:8m<6=831b544?::kb6?6=3f8mo7>5;|`63c<72=0;6=u+305953d<@:8n7E=>8:k:4?6=3`326=44i`094?=h:oi1<75rb45f>5<3290;w)=>7;35f>N4:l1C?<64i8294?=n100;66gn2;29?j4ak3:17pl:7e83>1<729q/?<9517`8L64b3A9:46g60;29?l?>2900el<50;9l6ce=831vn89l:187>5<7s-9:;7?9b:J06`=O;820e4>50;9j=<<722cj>7>5;n0eg?6=3th>;o4?:583>5}#;8=1=;l4H20f?M5602c2<7>5;h;:>5<>of:3:17bo>83:17d76:188md4=831d>km50;9~f01?290?6=4?{%123?71j2B8>h5G30:8m<6=831b544?::kb6?6=3f8mo7>5;|`630<72=0;6=u+305953d<@:8n7E=>8:k:4?6=3`326=44i`094?=h:oi1<75rb457>5<3290;w)=>7;35f>N4:l1C?<64i8294?=n100;66gn2;29?j4ak3:17pl;6e83>6<729q/?<951758L64b3A9:46g60;29?lg52900c?hl:188yg20;3:1?7>50z&052<6>>1C??k4H23;?l?72900el<50;9l6ce=831vn99=:180>5<7s-9:;7?97:J06`=O;820e4>50;9je7<722e9jn4?::a027=8391<7>t$234>4003A99i6F<199j=5<722cj>7>5;n0eg?6=3th?;=4?:283>5}#;8=1=;94H20f?M5602c2<7>5;hc1>5<?7;h;3>5<>i5nj0;66sm47c94?5=83:p(>?8:044?M55m2B8=55f9183>>of:3:17b00;6>4?:1y'741=9?=0D>o>83:17do=:188k7`d2900qo:98;297?6=8r.8=:4>669K77c<@:;37d7?:188md4=831d>km50;9~f10029086=4?{%123?71?2B8>h5G30:8m<6=831bm?4?::m1bf<722wi8;h50;194?6|,:;<6<88;I11a>N4911b5=4?::kb6?6=3f8mo7>5;|`72g<72:0;6=u+3059531<@:8n7E=>8:k:4?6=3`k96=44o3d`>5<i87>54;294~"49>0::o5G33g8L67?3`3;6=44i8;94?=ni;0;66a=fb83>>{e<191<7=50;2x 67028<<7E==e:J05==n190;66gn2;29?j4ak3:17pl;8383>6<729q/?<951758L64b3A9:46g60;29?lg52900c?hl:188yg2?83:1?7>50z&052<6>>1C??k4H23;?l?72900el<50;9l6ce=831vn99i:180>5<7s-9:;7?97:J06`=O;820e4>50;9je7<722e9jn4?::a7t$234>64c3A99i6F<199j=f<722c:h94?::m1b3<722wi?4650;194?6|,:;<6>N4911b5n4?::k2`1<722e9j;4?::a7=1=83>1<7>t$234>4c73A99i6F<199j=f<722cj;7>5;h13b?6=3f8m:7>5;|`0=2<72:0;6=u+305977b<@:8n7E=>8:k:g?6=3`;o87>5;n0e2?6=3th84;4?:583>5}#;8=1=h>4H20f?M5602c2o7>5;hc4>5<5<53;294~"49>08>i5G33g8L67?3`3h6=44i0f7>5<?7;h;`>5<5<4290;w)=>7;11`>N4:l1C?<64i8a94?=n9m>1<75`2g494?=zj:2?6=4;:183!56?3;n<6F<2d9K74>>o48o0;66a=f783>>{e;0>1<7=50;2x 6702:8o7E==e:J05==n1j0;66g>d583>>i5n?0;66sm39194?2=83:p(>?8:0g3?M55m2B8=55f9b83>>of?3:17d=?f;29?j4a>3:17pl<9283>6<729q/?<9533f8L64b3A9:46g6c;29?l7c<3:17bo>k3:17do8:188m66a2900c?h9:188yg5>:3:1?7>50z&052<4:m1C??k4H23;?l?d2900ee19K77c<@:;37d7l:188md1=831b?=h50;9l6c0=831vn>7>:180>5<7s-9:;7==d:J06`=O;820e4m50;9j5a2=831d>k850;9~f6>7290?6=4?{%123?7b82B8>h5G30:8m1<7>t$234>4c73A99i6F<199j=f<722cj;7>5;h13b?6=3f8m:7>5;|`777<72<0;6=u+305953g<@:8n7E=>8:k:4?6=3`326=44i8d94?=ni;0;66a=fb83>>{e;kk1<7;50;2x 67028l6:186>5<7s-9:;7?9a:J06`=O;820e4>50;9j=<<722c2j7>5;hc1>5<?7;h;3>5<>of:3:17b0;684?:1y'741=9?k0D>o>83:17d76:188m<`=831bm?4?::m1bf<722wi?o850;794?6|,:;<6<8n;I11a>N4911b5=4?::k:=?6=3`3m6=44i`094?=h:oi1<75rb2`6>5<2290;w)=>7;35e>N4:l1C?<64i8294?=n100;66g6f;29?lg52900c?hl:188yg5e<3:197>50z&052<6>h1C??k4H23;?l?72900e4750;9j=c<722cj>7>5;n0eg?6=3th8n>4?:483>5}#;8=1=;o4H20f?M5602c2<7>5;h;:>5<>i5nj0;66sm42194?3=83:p(>?8:04b?M55m2B8=55f9183>>o>13:17d7i:188md4=831d>km50;9~f34629086=4?{%123?7c02B8>h5G30:8 4>c2=20e<6>:188m4>52900c?h9:188yg2b>3:1?7>50z&052<6l11C??k4H23;?!7?l3;27d?71;29?l7?:3:17b"60m0:9i5f19394?=n9181<75f19194?=h:o<1<75rb40a>5<3290;w)=>7;3ge>N4:l1C?<64$0:g>105<5<mo7>54;294~"49>0:hl5G33g8L67?3-;3h7?;;h3;5?6=3`;3>7>5;h3;7?6=3f8m:7>5;|`7`f<72=0;6=u+30595ag<@:8n7E=>8:&24?::m1b3<722wi?>950;694?6|,:;<6N4911/=5j51758m4>62900e<6=:188m4>42900c?h9:188yg2cj3:197>50z&052<6lm1C??k4H23;?!7?l3887d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0:;6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e<;91<7;50;2x 67028no7E==e:J05==#91n1?>5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj:i;6=4::183!56?3;oh6F<2d9K74><,82o685f19394?=n9181<75f19194?=n91>1<75`2g494?=zj<:=6=4::183!56?3;oh6F<2d9K74><,82o6<8<;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th8o:4?:483>5}#;8=1=ij4H20f?M5602.:4i49;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th>=54?:483>5}#;8=1=ij4H20f?M5602.:4i4=8:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi89k50;794?6|,:;<6N4911/=5j5449j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn8<=:186>5<7s-9:;7?kd:J06`=O;820(<6k:3d8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;=1;291?6=8r.8=:4>de9K77c<@:;37)?7d;67?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl:2183>0<729q/?<951ef8L64b3A9:46*>8e875>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm60g94?2=83:p(>?8:0fb?M55m2B8=55+19f90a=n91;1<75f19094?=n9191<75`2g494?=zj<8=6=4::183!56?3;oh6F<2d9K74><,82o69=4i0:2>5<5<5<54;294~"49>0:hl5G33g8L67?3-;3h7<>;h3;5?6=3`;3>7>5;h3;7?6=3f8m:7>5;|`5``<72=0;6=u+30595ag<@:8n7E=>8:&25<7s-9:;7?kd:J06`=O;820(<6k:49j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn;97:187>5<7s-9:;7?ka:J06`=O;820(<6k:028m4>62900e<6=:188m4>42900c?h9:188yg00>3:197>50z&052<6lm1C??k4H23;?!7?l3;>=6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e>>?1<7:50;2x 67028nj7E==e:J05==#91n1=;94i0:2>5<5<?7;%3;`?>b3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`666<72=0;6=u+30595ag<@:8n7E=>8:&24?::m1b3<722wi9?m50;794?6|,:;<6N4911/=5j5549j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn85<7s-9:;7?ka:J06`=O;820(<6k:028m4>62900e<6=:188m4>42900c?h9:188yg2al3:197>50z&052<6lm1C??k4H23;?!7?l3;><6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e5<5<5<mn7>55;294~"49>0:hi5G33g8L67?3-;3h7h4i0:2>5<5<5<55;294~"49>0:hi5G33g8L67?3-;3h7?80:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi:ko50;794?6|,:;<6N4911/=5j54:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi:kj50;794?6|,:;<6N4911/=5j5139j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn9h<:186>5<7s-9:;7?kd:J06`=O;820(<6k:0c8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo:j3;291?6=8r.8=:4>de9K77c<@:;37)?7d;c0?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl;e383>0<729q/?<951ef8L64b3A9:46*>8e822`=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb5g3>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>725<5<?7;%3;`?73?2c:4<4?::k2<7<722e9j;4?::a0`2=83?1<7>t$234>4bc3A99i6F<199'5=b=981b=5?50;9j5=4=831b=5=50;9j5=2=831d>k850;9~f1c2290>6=4?{%123?7cl2B8>h5G30:8 4>c2h90e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg2bi3:187>50z&052<6m81C??k4H23;?l7?93:17d?72;29?l57n3:17b0;684?:1y'741=9mn0D>"60m0::k5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj=oi6=4;:183!56?3;n>6F<2d9K74>5<5<53;294~"49>0:h55G33g8L67?3-;3h7;=;h3;5?6=3`;3>7>5;n0e2?6=3th>?;4?:583>5}#;8=1=io4H20f?M5602.:4i4;2:k2<4<722c:4?4?::k2<6<722e9j;4?::a724=83>1<7>t$234>4bf3A99i6F<199'5=b=9=k0e<6>:188m4>52900e<6<:188k7`12900qo=81;290?6=8r.8=:4>d`9K77c<@:;37)?7d;3;?l7?93:17d?72;29?l7?;3:17b"60m0?7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0:8l5f19394?=n9181<75f19194?=h:o<1<75rb776>5<3290;w)=>7;3ge>N4:l1C?<64$0:g>42f3`;3=7>5;h3;6?6=3`;3?7>5;n0e2?6=3th=994?:583>5}#;8=1=io4H20f?M5602.:4i4>4`9j5=7=831b=5<50;9j5=5=831d>k850;9~f334290?6=4?{%123?7ci2B8>h5G30:8 4>c21h0e<6>:188m4>52900e<6<:188k7`12900qo8:2;290?6=8r.8=:4>d`9K77c<@:;37)?7d;:a?l7?93:17d?72;29?l7?;3:17b"60m03n6g>8083>>o60;0;66g>8283>>i5n?0;66sm64294?2=83:p(>?8:0fb?M55m2B8=55+19f9<,82o65l4i0:2>5<5<?7;%3;`?363`;3=7>5;h3;6?6=3`;3?7>5;n0e2?6=3th=n44?:583>5}#;8=1=io4H20f?M5602.:4i4:1:k2<4<722c:4?4?::k2<6<722e9j;4?::a2g5=83>1<7>t$234>4bf3A99i6F<199'5=b==81b=5?50;9j5=4=831b=5=50;9l6c0=831vn;ok:187>5<7s-9:;7?ka:J06`=O;820(<6k:438m4>62900e<6=:188m4>42900c?h9:188yg0f?3:187>50z&052<6lh1C??k4H23;?!7?l3?:7d?71;29?l7?:3:17d?73;29?j4a>3:17pl9a083>1<729q/?<951ec8L64b3A9:46*>8e865>o6080;66g>8383>>o60:0;66a=f783>>{e>0h1<7:50;2x 67028nj7E==e:J05==#91n19<5f19394?=n9181<75f19194?=h:o<1<75rb7:f>5<3290;w)=>7;3ge>N4:l1C?<64$0:g>075<5<55;294~"49>0:hi5G33g8L67?3-;3h7?89:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi95l50;794?6|,:;<6N4911/=5j515f8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;7a;290?6=8r.8=:4>d`9K77c<@:;37)?7d;37e>o6080;66g>8383>>o60:0;66a=f783>>{e=191<7;50;2x 67028no7E==e:J05==#91n1:?5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj?n36=4;:183!56?3;om6F<2d9K74><,82o6<;7;h3;5?6=3`;3>7>5;h3;7?6=3f8m:7>5;|`6bc<72=0;6=u+30595ag<@:8n7E=>8:&24?::m1b3<722wi88o50;794?6|,:;<6N4911/=5j51708m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;m6;290?6=8r.8=:4>d`9K77c<@:;37)?7d;36<>o6080;66g>8383>>o60:0;66a=f783>>{e<<21<7;50;2x 67028no7E==e:J05==#91n1=:84i0:2>5<5<5<357>55;294~"49>0:hi5G33g8L67?3-;3h78>;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th?4n4?:583>5}#;8=1=io4H20f?M5602.:4i4;b:k2<4<722c:4?4?::k2<6<722e9j;4?::a0=d=83?1<7>t$234>4bc3A99i6F<199'5=b=i?1b=5?50;9j5=4=831b=5=50;9j5=2=831d>k850;9~f3>1290>6=4?{%123?7cl2B8>h5G30:8 4>c28>n7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0:8h5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj?296=4::183!56?3;oh6F<2d9K74><,82o6<:j;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th=4=4?:483>5}#;8=1=ij4H20f?M5602.:4i4>4d9j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn;9j:186>5<7s-9:;7?kd:J06`=O;820(<6k:06f?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl97b83>0<729q/?<951ef8L64b3A9:46*>8e820`=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb75b>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>42b3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`532<72<0;6=u+30595ab<@:8n7E=>8:&2k850;9~f351290?6=4?{%123?7ci2B8>h5G30:8 4>c28>j7d?71;29?l7?:3:17d?73;29?j4a>3:17pl93e83>1<729q/?<951ec8L64b3A9:46*>8e820d=n91;1<75f19094?=n9191<75`2g494?=zj?9h6=4::183!56?3;oh6F<2d9K74><,82o64l4i0:2>5<5<5<54;294~"49>0:hl5G33g8L67?3-;3h7?;a:k2<4<722c:4?4?::k2<6<722e9j;4?::a7fe=83?1<7>t$234>4bc3A99i6F<199'5=b=9?:0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg5dn3:197>50z&052<6lm1C??k4H23;?!7?l3?87d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0::=5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj:no6=4::183!56?3;oh6F<2d9K74><,82o68=4i0:2>5<5<5<54;294~"49>0:hl5G33g8L67?3-;3h7?;a:k2<4<722c:4?4?::k2<6<722e9j;4?::a7`>=83?1<7>t$234>4bc3A99i6F<199'5=b=9?<0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg5bj3:197>50z&052<6lm1C??k4H23;?!7?l3?87d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0:8l5f19394?=n9181<75f19194?=h:o<1<75rb2d5>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>4073`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`0b<<72<0;6=u+30595ab<@:8n7E=>8:&24?::k2<1<722e9j;4?::a717=83>1<7>t$234>4bf3A99i6F<199'5=b=9=k0e<6>:188m4>52900e<6<:188k7`12900qo:?4;291?6=8r.8=:4>de9K77c<@:;37)?7d;354>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm41594?3=83:p(>?8:0fg?M55m2B8=55+19f916=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb21e>5<3290;w)=>7;3ge>N4:l1C?<64$0:g>42f3`;3=7>5;h3;6?6=3`;3?7>5;n0e2?6=3th?=?4?:483>5}#;8=1=ij4H20f?M5602.:4i4>619j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn9?::186>5<7s-9:;7?kd:J06`=O;820(<6k:418m4>62900e<6=:188m4>42900e<6;:188k7`12900qo=d`9K77c<@:;37)?7d;37e>o6080;66g>8383>>o60:0;66a=f783>>{e<;<1<7;50;2x 67028no7E==e:J05==#91n18n5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj:9i6=4;:183!56?3;om6F<2d9K74><,82o6<:n;h3;5?6=3`;3>7>5;h3;7?6=3f8m:7>5;|`07<<72=0;6=u+30595ag<@:8n7E=>8:&2=9:187>5<7s-9:;7?ka:J06`=O;820(<6k:06b?l7?93:17d?72;29?l7?;3:17b"60m02n6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e>=>1<7:50;2x 67028nj7E==e:J05==#91n1=9o4i0:2>5<5<?7;%3;`?73m2c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a0<2=83?1<7>t$234>4bc3A99i6F<199'5=b=9:188m4>52900e<6<:188m4>32900c?h9:188yg2e13:197>50z&052<6lm1C??k4H23;?!7?l3>0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg24n3:187>50z&052<6lh1C??k4H23;?!7?l39;7d?71;29?l7?:3:17d?73;29?j4a>3:17pl;4183>0<729q/?<951ef8L64b3A9:46*>8e8:3>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm45194?3=83:p(>?8:0fg?M55m2B8=55+19f95035<5<?7;h;3>5<5<3290;w)=>7;35`>N4:l1C?<64i8294?=ni;0;66g=fe83>>i5nj0;66sm49394?2=83:p(>?8:04g?M55m2B8=55f9183>>of:3:17d7<729q/?<951e58L64b3A9:46*>8e816>o6080;66a=f783>>{e=<31<7<50;2x 67028n<7E==e:J05==#91n1>?5f19394?=h:o<1<75rb474>5<5290;w)=>7;3g3>N4:l1C?<64$0:g>745<97>52;294~"49>0:h:5G33g8L67?3-;3h7<=;h3;5?6=3f8m:7>5;|`616<72;0;6=u+30595a1<@:8n7E=>8:&2N4911/=5j5239j5=7=831d>k850;9~f02a29096=4?{%123?7c?2B8>h5G30:8 4>c2;80e<6>:188k7`12900qo;;d;296?6=8r.8=:4>d69K77c<@:;37)?7d;01?l7?93:17b"60m09>6g>8083>>i5n?0;66sm55;94?4=83:p(>?8:0f4?M55m2B8=55+19f967=n91;1<75`2g494?=zj<,82o6?<4i0:2>5<?7;%3;`?2f3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`7g7<72=0;6=u+305953?<@:8n7E=>8:k:4?6=3`3m6=44i`094?=h:oi1<75rb55g>5<4290;w)=>7;353>N4:l1C?<64i8294?=ni;0;66a=fb83>>{e<>h1<7=50;2x 67028<<7E==e:J05==n190;66gn2;29?j4ak3:17pl;bc83>0<729q/?<951ef8L64b3A9:46*>8e823g=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb5``>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>41c3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`7f5<72=0;6=u+305953?<@:8n7E=>8:k:4?6=3`3m6=44i`094?=h:oi1<75rb5`1>5<3290;w)=>7;35g>N4:l1C?<64i8294?=ni;0;66g=fc83>>i5nj0;66sm4`494?2=83:p(>?8:04:?M55m2B8=55f9183>>o>n3:17do=:188k7`d2900qo:n4;290?6=8r.8=:4>689K77c<@:;37d7?:188m<`=831bm?4?::m1bf<722wi8l<50;694?6|,:;<6<86;I11a>N4911b5=4?::k:b?6=3`k96=44o3d`>5<j<7>54;294~"49>0::45G33g8L67?3`3;6=44i8d94?=ni;0;66a=fb83>>{eo>83:17d7i:188md4=831d>km50;9~f1ec290?6=4?{%123?7112B8>h5G30:8m<6=831b5k4?::kb6?6=3f8mo7>5;|`7gg<72=0;6=u+305953?<@:8n7E=>8:k:4?6=3`3m6=44i`094?=h:oi1<75rb5a:>5<3290;w)=>7;35=>N4:l1C?<64i8294?=n1o0;66gn2;29?j4ak3:17pl<8883>0<729q/?<951ef8L64b3A9:46*>8e8;e>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm39c94?3=83:p(>?8:0fg?M55m2B8=55+19f95<2290;w)=>7;3g`>N4:l1C?<64$0:g>=g5<5<?7;%3;`?>f3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`08:&24?::k2<1<722e9j;4?::a7=c=83?1<7>t$234>4bc3A99i6F<199'5=b=0h1b=5?50;9j5=4=831b=5=50;9j5=2=831d>k850;9~f6>a290>6=4?{%123?7cl2B8>h5G30:8 4>c21k0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg5>83:197>50z&052<6lm1C??k4H23;?!7?l32j7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0:;<5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj==h6=4::183!56?3;oh6F<2d9K74><,82o6<9;;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th?584?:483>5}#;8=1=ij4H20f?M5602.:4i4>5:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi84=50;794?6|,:;<6N4911/=5j55b9j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn969:186>5<7s-9:;7?kd:J06`=O;820(<6k:05g?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl;3883>0<729q/?<951ef8L64b3A9:46*>8e8221=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb51a>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>d35<5<?7;%3;`?563`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`7g6<72<0;6=u+30595ab<@:8n7E=>8:&24?::k2<1<722e9j;4?::a0f2=83?1<7>t$234>4bc3A99i6F<199'5=b=0j1b=5?50;9j5=4=831b=5=50;9j5=2=831d>k850;9~f1d6290>6=4?{%123?7cl2B8>h5G30:8 4>c28>27d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0:845f19394?=n9181<75f19194?=n91>1<75`2g494?=zj=km6=4::183!56?3;oh6F<2d9K74><,82o6<:6;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th?m:4?:483>5}#;8=1=ij4H20f?M5602.:4i47c:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi8l;50;794?6|,:;<6N4911/=5j58b9j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn9o<:186>5<7s-9:;7?kd:J06`=O;820(<6k:9a8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo:n1;291?6=8r.8=:4>de9K77c<@:;37)?7d;:`?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl;d183>0<729q/?<951ef8L64b3A9:46*>8e8;g>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm4bg94?3=83:p(>?8:0fg?M55m2B8=55+19f95<2290;w)=>7;3g`>N4:l1C?<64$0:g>=e5<5<?7;%3;`?023`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`7gd<72<0;6=u+30595ab<@:8n7E=>8:&24?::k2<1<722e9j;4?::a7ge=83?1<7>t$234>4bc3A99i6F<199'5=b=9>i0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg25:3:197>50z&052<6lm1C??k4H23;?!7?l3;>56g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e<8=1<7;50;2x 67028no7E==e:J05==#91n1=874i0:2>5<5<5<;57>55;294~"49>0:hi5G33g8L67?3-;3h7?:9:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi?kl50;794?6|,:;<6N4911/=5j514;8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo=jd;291?6=8r.8=:4>de9K77c<@:;37)?7d;36=>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm3ed94?3=83:p(>?8:0fg?M55m2B8=55+19f950?5<5<?7;%3;`?71n2c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a073=83?1<7>t$234>4bc3A99i6F<199'5=b=9>1b=5?50;9j5=4=831b=5=50;9j5=2=831d>k850;9~f151290>6=4?{%123?7cl2B8>h5G30:8 4>c28=27d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0:9n5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj=3<6=4::183!56?3;oh6F<2d9K74><,82o6<;n;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th8o?4?:483>5}#;8=1=ij4H20f?M5602.:4i468:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi?nk50;794?6|,:;<6N4911/=5j515:8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo=lb;291?6=8r.8=:4>de9K77c<@:;37)?7d;37<>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm3ea94?3=83:p(>?8:0fg?M55m2B8=55+19f951>5<5<?7;%3;`?7302c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a7`g=83?1<7>t$234>4bc3A99i6F<199'5=b=9=20e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg5b?3:197>50z&052<6lm1C??k4H23;?!7?l3;?46g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e;o21<7;50;2x 67028no7E==e:J05==#91n1=964i0:2>5<5<5<55;294~"49>0:hi5G33g8L67?3-;3h7?;8:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi8=850;794?6|,:;<6N4911/=5j515:8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo:?3;291?6=8r.8=:4>de9K77c<@:;37)?7d;37<>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm40694?3=83:p(>?8:0fg?M55m2B8=55+19f951>5<5<?7;%3;`?7302c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a17`=83?1<7>t$234>4bc3A99i6F<199'5=b=9>n0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg2bn3:197>50z&052<6lm1C??k4H23;?!7?l3?0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg2bm3:197>50z&052<6lm1C??k4H23;?!7?l3<;7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0::6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e=131<7;50;2x 67028no7E==e:J05==#91n1=9j4i0:2>5<5<5<54;294~"49>0:hl5G33g8L67?3-;3h7?;a:k2<4<722c:4?4?::k2<6<722e9j;4?::a1t$234>4bc3A99i6F<199'5=b=9=n0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg3>k3:187>50z&052<6lh1C??k4H23;?!7?l3;?m6g>8083>>o60;0;66g>8283>>i5n?0;66sm58`94?3=83:p(>?8:0fg?M55m2B8=55+19f951b5<5<?7;%3;`?73i2c:4<4?::k2<7<722c:4>4?::m1b3<722wi94750;794?6|,:;<6N4911/=5j515f8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;68;290?6=8r.8=:4>d`9K77c<@:;37)?7d;37e>o6080;66g>8383>>o60:0;66a=f783>>{e=0=1<7;50;2x 67028no7E==e:J05==#91n1=9j4i0:2>5<5<5<54;294~"49>0:hl5G33g8L67?3-;3h7?;a:k2<4<722c:4?4?::k2<6<722e9j;4?::a1<3=83?1<7>t$234>4bc3A99i6F<199'5=b=9=n0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg3><3:187>50z&052<6lh1C??k4H23;?!7?l3;?m6g>8083>>o60;0;66g>8283>>i5n?0;66sm58194?3=83:p(>?8:0fg?M55m2B8=55+19f951b5<5<?7;%3;`?73i2c:4<4?::k2<7<722c:4>4?::m1b3<722wi94?50;794?6|,:;<6N4911/=5j515f8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;60;290?6=8r.8=:4>d`9K77c<@:;37)?7d;37e>o6080;66g>8383>>o60:0;66a=f783>>{e=1l1<7;50;2x 67028no7E==e:J05==#91n1=9j4i0:2>5<5<5<54;294~"49>0:hl5G33g8L67?3-;3h7?;a:k2<4<722c:4?4?::k2<6<722e9j;4?::a1=e=83>1<7>t$234>4bf3A99i6F<199'5=b=9=k0e<6>:188m4>52900e<6<:188k7`12900qo;70;291?6=8r.8=:4>de9K77c<@:;37)?7d;`8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;mf;291?6=8r.8=:4>de9K77c<@:;37)?7d;1f?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl;f483>0<729q/?<951ef8L64b3A9:46*>8e8;?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl9c183>0<729q/?<951ef8L64b3A9:46*>8e86?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl;a983>0<729q/?<951ef8L64b3A9:46*>8e812>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm4`;94?3=83:p(>?8:0fg?M55m2B8=55+19f9e3=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb5`f>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>d25<5<?7;%3;`?303`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`6g4<72<0;6=u+30595ab<@:8n7E=>8:&24?::k2<1<722e9j;4?::a1f4=83?1<7>t$234>4bc3A99i6F<199'5=b==>1b=5?50;9j5=4=831b=5=50;9j5=2=831d>k850;9~f0e4290>6=4?{%123?7cl2B8>h5G30:8 4>c2<=0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg3d<3:197>50z&052<6lm1C??k4H23;?!7?l3?<7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0>;6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e=j<1<7;50;2x 67028no7E==e:J05==#91n19:5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj?n<6=4;:183!56?3;om6F<2d9K74><,82o6?;4i0:2>5<5<?7;%3;`?303`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`546<72=0;6=u+30595ag<@:8n7E=>8:&24?::m1b3<722wi:n750;794?6|,:;<6N4911/=5j5229j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn9<>:186>5<7s-9:;7?kd:J06`=O;820(<6k:838m4>62900e<6=:188m4>42900e<6;:188k7`12900qo:;c;291?6=8r.8=:4>de9K77c<@:;37)?7d;363>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm52g94?3=83:p(>?8:0fg?M55m2B8=55+19f9a>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm52f94?3=83:p(>?8:0fg?M55m2B8=55+19f95255<5<?7;%3;`?313`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`7`=<72<0;6=u+30595ab<@:8n7E=>8:&2k850;9~f37a290>6=4?{%123?7cl2B8>h5G30:8 4>c2<20e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg0583:187>50z&052<6lh1C??k4H23;?!7?l3;>h6g>8083>>o60;0;66g>8283>>i5n?0;66sm60a94?3=83:p(>?8:0fg?M55m2B8=55+19f95235<5<?7;%3;`?333`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`7b1<72<0;6=u+30595ab<@:8n7E=>8:&2k850;9~f077290>6=4?{%123?7cl2B8>h5G30:8 4>c2:?0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg3493:187>50z&052<6lh1C??k4H23;?!7?l3;;7d?71;29?l7?:3:17d?73;29?j4a>3:17pl;3d83>0<729q/?<951ef8L64b3A9:46*>8e8b?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl;3e83>1<729q/?<951ec8L64b3A9:46*>8e86b>o6080;66g>8383>>o60:0;66a=f783>>{e;j91<7;50;2x 67028no7E==e:J05==#91n1=:5f19394?=n9181<75f19194?=n91>1<75`2g494?=zj=>:6=4::183!56?3;oh6F<2d9K74><,82o6;=4i0:2>5<5<5<?>7>54;294~"49>0:hl5G33g8L67?3-;3h7j4i0:2>5<5<?7;%3;`?71?2c:4<4?::k2<7<722c:4>4?::m1b3<722wi9>750;694?6|,:;<6N4911/=5j5419j5=7=831b=5<50;9j5=5=831d>k850;9~f0>3290>6=4?{%123?7cl2B8>h5G30:8 4>c21n0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg2ci3:197>50z&052<6lm1C??k4H23;?!7?l3><7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0m7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m0:::5f19394?=n9181<75f19194?=h:o<1<75rb516>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>455<5<?7;%3;`?73i2c:4<4?::k2<7<722c:4>4?::m1b3<722wi:>k50;694?6|,:;<6N4911/=5j515c8m4>62900e<6=:188m4>42900c?h9:188yg0ek3:187>50z&052<6m81C??k4H23;?l7?93:17d?72;29?l57n3:17b"60m0:8l5f19394?=n9181<75f19194?=h:o<1<75rb7`f>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>43e3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`5f3<72=0;6=u+30595`7<@:8n7E=>8:k2<4<722c:4?4?::k04c<722e9j;4?::a2g1=83>1<7>t$234>4bf3A99i6F<199'5=b=9=k0e<6>:188m4>52900e<6<:188k7`12900qo8m8;291?6=8r.8=:4>de9K77c<@:;37)?7d;36f>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm6c294?2=83:p(>?8:0g2?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb7`2>5<3290;w)=>7;3ge>N4:l1C?<64$0:g>42f3`;3=7>5;h3;6?6=3`;3?7>5;n0e2?6=3th=n?4?:483>5}#;8=1=ij4H20f?M5602.:4i4>5c9j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn;on:187>5<7s-9:;7?j1:J06`=O;820e<6>:188m4>52900e>>i:188k7`12900qo8nb;290?6=8r.8=:4>d`9K77c<@:;37)?7d;37e>o6080;66g>8383>>o60:0;66a=f783>>{e>hi1<7;50;2x 67028no7E==e:J05==#91n1=8l4i0:2>5<5<5<54;294~"49>0:i<5G33g8L67?3`;3=7>5;h3;6?6=3`9;j7>5;n0e2?6=3th=m84?:583>5}#;8=1=io4H20f?M5602.:4i4>4`9j5=7=831b=5<50;9j5=5=831d>k850;9~f3g1290>6=4?{%123?7cl2B8>h5G30:8 4>c28?i7d?71;29?l7?:3:17d?73;29?l7?<3:17bo6080;66g>8383>>o48o0;66a=f783>>{e>0l1<7:50;2x 67028nj7E==e:J05==#91n1=9o4i0:2>5<5<?7;%3;`?72j2c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a2<>=83>1<7>t$234>4c63A99i6F<199j5=7=831b=5<50;9j75`=831d>k850;9~f3?>290?6=4?{%123?7ci2B8>h5G30:8 4>c28>j7d?71;29?l7?:3:17d?73;29?j4a>3:17pl99`83>0<729q/?<951ef8L64b3A9:46*>8e821g=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb7:a>5<3290;w)=>7;3f5>N4:l1C?<64i0:2>5<5<?7;%3;`?73i2c:4<4?::k2<7<722c:4>4?::m1b3<722wi:5j50;794?6|,:;<6N4911/=5j514`8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo:i6;290?6=8r.8=:4>e09K77c<@:;37d?71;29?l7?:3:17d=?f;29?j4a>3:17pl;f883>1<729q/?<951ec8L64b3A9:46*>8e852>o6080;66g>8383>>o60:0;66a=f783>>{e5<5<5<54;294~"49>0:i<5G33g8L67?3`;3=7>5;h3;6?6=3`9;j7>5;n0e2?6=3th8o84?:483>5}#;8=1=ij4H20f?M5602.:4i4=7:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi?n850;794?6|,:;<6N4911/=5j515:8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;ie;290?6=8r.8=:4>e09K77c<@:;37d?71;29?l7?:3:17d=?f;29?j4a>3:17pl90183>0<729q/?<951ef8L64b3A9:46*>8e87=>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm61394?2=83:p(>?8:0fb?M55m2B8=55+19f955=n91;1<75f19094?=n9191<75`2g494?=zj<>;6=4;:183!56?3;n=6F<2d9K74>5<5<55;294~"49>0:hi5G33g8L67?3-;3h7?8;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th>8?4?:583>5}#;8=1=io4H20f?M5602.:4i4>669j5=7=831b=5<50;9j5=5=831d>k850;9~f345290>6=4?{%123?7cl2B8>h5G30:8 4>c2l1b=5?50;9j5=4=831b=5=50;9j5=2=831d>k850;9~f344290?6=4?{%123?7ci2B8>h5G30:8 4>c28>0e<6>:188m4>52900e<6<:188k7`12900qo=md;290?6=8r.8=:4>e09K77c<@:;37d?71;29?l7?:3:17d=?f;29?j4a>3:17pl0<729q/?<951ef8L64b3A9:46*>8e8:6>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm3cd94?3=83:p(>?8:0fg?M55m2B8=55+19f966=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb42;>5<3290;w)=>7;3f5>N4:l1C?<64i0:2>5<5<?7;%3;`?553`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`64d<72<0;6=u+30595ab<@:8n7E=>8:&24?::k2<1<722e9j;4?::a154=83?1<7>t$234>4bc3A99i6F<199'5=b=9>?0e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg32i3:1>7>50z&052<6l91C??k4H23;?l7?83:17bo6090;66a=f783>>{e>:?1<7<50;2x 67028n;7E==e:J05==n91:1<75`2g494?=zj<:86=4::183!56?3;oh6F<2d9K74><,82o6?k4i0:2>5<5<5<54;294~"49>0:i<5G33g8L67?3`;3=7>5;h3;6?6=3`9;j7>5;n0e2?6=3th>=<4?:483>5}#;8=1=ij4H20f?M5602.:4i4>f:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi9<<50;694?6|,:;<6;I11a>N4911b=5?50;9j5=4=831b?=h50;9l6c0=831vn8>j:186>5<7s-9:;7?kd:J06`=O;820(<6k:0a8m4>62900e<6=:188m4>42900e<6;:188k7`12900qo;?f;290?6=8r.8=:4>e09K77c<@:;37d?71;29?l7?:3:17d=?f;29?j4a>3:17pl;f683>0<729q/?<951ef8L64b3A9:46*>8e822`=n91;1<75f19094?=n9191<75f19694?=h:o<1<75rb5d;>5<3290;w)=>7;3f5>N4:l1C?<64i0:2>5<5<?7;%3;`?25<5<?7;h3;5?6=3`;3>7>5;h13b?6=3f8m:7>5;|`662<72<0;6=u+30595ab<@:8n7E=>8:&2k850;9~f04?29086=4?{%123?7c02B8>h5G30:8 4>c2h80e<6>:188m4>52900c?h9:188yg3513:187>50z&052<6m81C??k4H23;?l7?93:17d?72;29?l57n3:17b"60m0:<6g>8083>>o60;0;66g>8283>>i5n?0;66sm4eg94?3=83:p(>?8:0fg?M55m2B8=55+19f9g>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm4ed94?2=83:p(>?8:0g2?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb5g`>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>6`5<5<?7;h3;5?6=3`;3>7>5;h13b?6=3f8m:7>5;|`70c<72<0;6=u+30595ab<@:8n7E=>8:&25;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`715<72=0;6=u+30595`7<@:8n7E=>8:k2<4<722c:4?4?::k04c<722e9j;4?::a071=83?1<7>t$234>4bc3A99i6F<199'5=b=9:188m4>52900e<6<:188m4>32900c?h9:188yg2503:197>50z&052<6lm1C??k4H23;?!7?l3;=j6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e<;31<7:50;2x 67028o:7E==e:J05==n91;1<75f19094?=n;9l1<75`2g494?=zj?>o6=4::183!56?3;oh6F<2d9K74><,82o6<;m;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th=8h4?:483>5}#;8=1=ij4H20f?M5602.:4i46a:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi:9h50;694?6|,:;<6;I11a>N4911b=5?50;9j5=4=831b?=h50;9l6c0=831vn;:8:186>5<7s-9:;7?kd:J06`=O;820(<6k:07a?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl94983>0<729q/?<951ef8L64b3A9:46*>8e8:e>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm65;94?2=83:p(>?8:0g2?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb240>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>43e3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`021<72<0;6=u+30595ab<@:8n7E=>8:&2i2c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a733=83>1<7>t$234>4c63A99i6F<199j5=7=831b=5<50;9j75`=831d>k850;9~f63a290>6=4?{%123?7cl2B8>h5G30:8 4>c28?i7d?71;29?l7?:3:17d?73;29?l7?<3:17b90;684?:1y'741=9mn0D>"60m02m6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e;?;1<7:50;2x 67028o:7E==e:J05==n91;1<75f19094?=n;9l1<75`2g494?=zj:?i6=4::183!56?3;oh6F<2d9K74><,82o6<;m;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th89n4?:483>5}#;8=1=ij4H20f?M5602.:4i46a:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi?8j50;694?6|,:;<6;I11a>N4911b=5?50;9j5=4=831b?=h50;9l6c0=831vn;:n:186>5<7s-9:;7?kd:J06`=O;820(<6k:07a?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl94c83>0<729q/?<951ef8L64b3A9:46*>8e8:e>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm65a94?2=83:p(>?8:0g2?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb762>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>43e3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`507<72<0;6=u+30595ab<@:8n7E=>8:&2i2c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a215=83>1<7>t$234>4c63A99i6F<199j5=7=831b=5<50;9j75`=831d>k850;9~f630290>6=4?{%123?7cl2B8>h5G30:8 4>c28?i7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m02m6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e;<31<7:50;2x 67028o:7E==e:J05==n91;1<75f19094?=n;9l1<75`2g494?=zj:?86=4::183!56?3;oh6F<2d9K74><,82o6<;m;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n0e2?6=3th8994?:483>5}#;8=1=ij4H20f?M5602.:4i46a:k2<4<722c:4?4?::k2<6<722c:494?::m1b3<722wi?8;50;694?6|,:;<6;I11a>N4911b=5?50;9j5=4=831b?=h50;9l6c0=831vn>:i:186>5<7s-9:;7?kd:J06`=O;820(<6k:07a?l7?93:17d?72;29?l7?;3:17d?74;29?j4a>3:17pl<5183>0<729q/?<951ef8L64b3A9:46*>8e8:e>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm34394?2=83:p(>?8:0g2?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb26a>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>43e3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`00f<72<0;6=u+30595ab<@:8n7E=>8:&2i2c:4<4?::k2<7<722c:4>4?::k2<1<722e9j;4?::a71b=83>1<7>t$234>4c63A99i6F<199j5=7=831b=5<50;9j75`=831d>k850;9~f620290>6=4?{%123?7cl2B8>h5G30:8 4>c28?i7d?71;29?l7?:3:17d?73;29?l7?<3:17b"60m02m6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e;=31<7:50;2x 67028o:7E==e:J05==n91;1<75f19094?=n;9l1<75`2g494?=zj<9j6=4::183!56?3;oh6F<2d9K74><,82o6?=4i0:2>5<5<5<54;294~"49>0:i<5G33g8L67?3`;3=7>5;h3;6?6=3`9;j7>5;n0e2?6=3th=o;4?:483>5}#;8=1=ij4H20f?M5602.:4i4>699j5=7=831b=5<50;9j5=5=831b=5:50;9l6c0=831vn;m8:187>5<7s-9:;7?j1:J06`=O;820e<6>:188m4>52900e>>i:188k7`12900qo8l3;291?6=8r.8=:4>de9K77c<@:;37)?7d;35<>o6080;66g>8383>>o60:0;66g>8583>>i5n?0;66sm6b694?2=83:p(>?8:0g2?M55m2B8=55f19394?=n9181<75f31d94?=h:o<1<75rb7;6>5<2290;w)=>7;3g`>N4:l1C?<64$0:g>40?3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f8m:7>5;|`5=3<72=0;6=u+30595`7<@:8n7E=>8:k2<4<722c:4?4?::k04c<722e9j;4?::a2<4=83?1<7>t$234>4bc3A99i6F<199'5=b=9?20e<6>:188m4>52900e<6<:188m4>32900c?h9:188yg0>;3:187>50z&052<6m81C??k4H23;?l7?93:17d?72;29?l57n3:17b"60m0?o6g>8083>>o60;0;66g>8283>>o60=0;66a=f783>>{e<<91<7:50;2x 67028o:7E==e:J05==n91;1<75f19094?=n;9l1<75`2g494?=zj??26=49:183!56?3;oi6F<2d9K74><,82o6<8:;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n3g1?6=3f8m:7>5;|`6<0<72<0;6=u+30595a`<@:8n7E=>8:&2f290?6=4?{%123?7ck2B8>h5G30:8 4>c2?=0e<6>:188m4>52900e<6<:188k4b22900qo:7d;291?6=8r.8=:4>dg9K77c<@:;37)?7d;341>o6080;66g>8383>>o60:0;66g>8583>>i6l<0;66sm62594?0=83:p(>?8:0ff?M55m2B8=55+19f91`=n91;1<75f19094?=n9191<75f19694?=h9m?1<75`2g494?=zj?936=49:183!56?3;oi6F<2d9K74><,82o64l4i0:2>5<5<5<3:1?7;%3;`?3b3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f;o97>5;n0e2?6=3th=8=4?:783>5}#;8=1=ik4H20f?M5602.:4i46b:k2<4<722c:4?4?::k2<6<722c:494?::m2`0<722e9j;4?::a26d=83<1<7>t$234>4bb3A99i6F<199'5=b==l1b=5?50;9j5=4=831b=5=50;9j5=2=831d=i;50;9l6c0=831vn>mk:186>5<7s-9:;7?kf:J06`=O;820(<6k:06f?l7?93:17d?72;29?l7?;3:17d?74;29?j7c=3:17pl0<729q/?<951ed8L64b3A9:46*>8e8232=n91;1<75f19094?=n9191<75f19694?=h9m?1<75rb2fa>5<2290;w)=>7;3gb>N4:l1C?<64$0:g>42c3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f;o97>5;|`0``<72<0;6=u+30595a`<@:8n7E=>8:&21b=5?50;9j5=4=831b=5=50;9j5=2=831d=i;50;9~f6c>290>6=4?{%123?7cn2B8>h5G30:8 4>c28>o7d?71;29?l7?:3:17d?73;29?l7?<3:17b?k5;29?xd4mj0;684?:1y'741=9ml0D>"60m0:;:5f19394?=n9181<75f19194?=n91>1<75`1e794?=zj:l<6=4::183!56?3;oj6F<2d9K74><,82o6<:j;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n3g1?6=3th8jl4?:483>5}#;8=1=ih4H20f?M5602.:4i4>769j5=7=831b=5<50;9j5=5=831b=5:50;9l5a3=831vn9>::186>5<7s-9:;7?kf:J06`=O;820(<6k:06f?l7?93:17d?72;29?l7?;3:17d?74;29?j7c=3:17pl;0983>0<729q/?<951ed8L64b3A9:46*>8e8232=n91;1<75f19094?=n9191<75f19694?=h9m?1<75rb530>5<2290;w)=>7;3gb>N4:l1C?<64$0:g>42b3`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f;o97>5;|`753<72<0;6=u+30595a`<@:8n7E=>8:&21b=5?50;9j5=4=831b=5=50;9j5=2=831d=i;50;9~f143290>6=4?{%123?7cn2B8>h5G30:8 4>c2:i0e<6>:188m4>52900e<6<:188m4>32900c50z&052<6lo1C??k4H23;?!7?l3;8083>>o60;0;66g>8283>>o60=0;66a>d483>>{e>=?1<7850;2x 67028nn7E==e:J05==#91n19h5f19394?=n9181<75f19194?=n91>1<75`1e794?=h:o<1<75rb5`b>5<1290;w)=>7;3ga>N4:l1C?<64$0:g>4123`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f;o97>5;n0e2?6=3th?ni4?:583>5}#;8=1=im4H20f?M5602.:4i4>4b9j5=7=831b=5<50;9j5=5=831d=i;50;9~f15?290?6=4?{%123?7ck2B8>h5G30:8 4>c28>j7d?71;29?l7?:3:17d?73;29?j7c=3:17pl;b483>0<729q/?<951ed8L64b3A9:46*>8e85<>o6080;66g>8383>>o60:0;66g>8583>>i6l<0;66sm4c494?3=83:p(>?8:0fe?M55m2B8=55+19f92==n91;1<75f19094?=n9191<75f19694?=h9m?1<75rb5`4>5<2290;w)=>7;3gb>N4:l1C?<64$0:g>3>5<5<6=44}c6be?6==3:1?7;%3;`?023`;3=7>5;h3;6?6=3`;3?7>5;h3;0?6=3f;o97>5;|`7eg<72<0;6=u+30595a`<@:8n7E=>8:&24?::k2<1<722e:h84?::a0de=83?1<7>t$234>4ba3A99i6F<199'5=b=><1b=5?50;9j5=4=831b=5=50;9j5=2=831d=i;50;9~f1gc290>6=4?{%123?7cn2B8>h5G30:8 4>c2??0e<6>:188m4>52900e<6<:188m4>32900c50z&052<6lo1C??k4H23;?!7?l3<>7d?71;29?l7?:3:17d?73;29?l7?<3:17b?k5;29?xd3l;0;684?:1y'741=9ml0D>"60m0=96g>8083>>o60;0;66g>8283>>o60=0;66a>d483>>{e1<75`1e794?=zj=2n6=4;:183!56?3;oo6F<2d9K74><,82o6i5f19394?=n9181<75f19194?=h9m?1<75rb5;5>5<3290;w)=>7;3gg>N4:l1C?<64$0:g>a=n91;1<75f19094?=n9191<75`1e794?=zj=;m6=4::183!56?3;oj6F<2d9K74><,82o6<:7;h3;5?6=3`;3>7>5;h3;7?6=3`;387>5;n3g1?6=3th8o<4?:483>5}#;8=1=ih4H20f?M5602.:4i4>789j5=7=831b=5<50;9j5=5=831b=5:50;9l5a3=831vn9=8:186>5<7s-9:;7?kf:J06`=O;820(<6k:2f8m4>62900e<6=:188m4>42900e<6;:188k4b22900qo;7d;291?6=8r.8=:4>dg9K77c<@:;37)?7d;37`>o6080;66g>8383>>o60:0;66g>8583>>i6l<0;66sm4cd94?3=83:p(>?8:0fe?M55m2B8=55+19f966=n91;1<75f19094?=n9191<75f19694?=h9m?1<75rb77a>5<2290;w)=>7;3gf>N4:l1C?<64$0:g>7?5<5<3:1?7;%3;`?15<5<6=44o3d5>5<55;294~"49>0:hk5G33g8L67?3-;3h7?9e:k2<4<722c:4?4?::k2<6<722c:494?::m2`0<722wi9kj50;694?6|,:;<6N4911/=5j5a39j5=7=831b=5<50;9l5a3=831d>k850;9~f15f290>6=4?{%123?7cn2B8>h5G30:8 4>c2130e<6>:188m4>52900e<6<:188m4>32900c3:1:7>50z&052<6ll1C??k4H23;?!7?l3?0e<6>:188m4>52900e<6<:188m4>32900cdd9K77c<@:;37)?7d;;8m4>62900e<6=:188m4>42900e<6;:188k4b22900c?h9:188yv05l3:1>vP92e9>167=:o<0q~=97;2934}Y;?=01;=<:828961320:01;67:82893>>20:018jk:82890bb20:018k>:82890c520:018k<:82890c320:018k::82890c120:018k8:82890c?20:018ji:82890c720:018k6:828902320:018:<:828905520:018=l:828905a20:018=;:828905020:01989:8f8910120o01>98:23a?850039:n63<78805g=:;>i1?67e349b:?03a<49k16?:k530`890`420:018h;:82890`220:018h9:82890`020:018h7:82890`>20:018hn:82890`e20:0189;:828901220:01897:828901>20:0189n:828901e20:0189l:828901c20:0189j:828901a20:01899:828901020:018o6:82890gf20:018ok:82890gb20:018oi:82890d720:018l>:82890d520:018l<:82890d320:018om:82890gd20:0199i:82891>720:0196=:82891>420:019l;:828910e20:0198i:828910020:01987:828910>20:0198n:828910b20:0198l:828911720:0199>:828911520:0199<:828910c20:019=<:82896d420:01>l;:82896d220:01>l9:82896d020:01>l7:82896d>20:01>ln:828915520:01;jm:82893bf20:0196>:82891e520:0199k:828911e20:019l?:82891d520:019o9:82891g320:019o=:82891g720:019oj:82891ea20:019mk:82891ee20:019m6:828yv51>3:1?vP<679>265=1016?::5a39~w3>0290?=vP9869>265=1o16?::59g9>1ab=1o169ik59g9>1`7=1o169h<59g9>1`5=1o169h:59g9>1`3=1o169h859g9>1`1=1o169h659g9>1a`=1o169h>59g9>1`?=1o169>m59g9>16`=1o169>:59g9>161=1o169k=59g9>1c2=1o169k;59g9>1c0=1o169k959g9>1c>=1o169k759g9>1cg=1o169kl59g9>1d?=1o169lo59g9>1db=1o169lk59g9>1d`=1o169o>59g9>1g7=1o169o<59g9>1g5=1o169o:59g9>1dd=1o169lm59g9>065=1o16?o=59g9>7g2=1o16?o;59g9>7g0=1o16?o959g9>7g>=1o16?o759g9>7gg=1o168><59g9>0f4=1o168o>59g9>0g4=:oh019o9:8d891g320l019o=:8d891g720l019oj:3da?82dn33m70:ld;;e?82dj33m70:l9;;e?83?83;3=63;d782<5=z{?lj6=4={_4ee>;1nh09j;5rs712>5<5sW<8=639de81b3=z{?lo6=4={_4e`>;1nm09j;5rs7d`>5<2sW66a34{t==91<77`d34>?o7?73:p065=83c;13b>;3;:09jn5244095=5<5=3<6<6=;|q72g<72;q68;l52ga8905c28287p}<7083>0}:64434>=:7==4:?723<4:?16?:?52g48yv50<3:19v3<7581bf=:43334?i:7?71:?6<5<60;1v>9::18082f13;3863;bd82<1=:;><1>k84}r7f=?6==r7>i44=fb9>030=;8n01989:23f?821>39:j63;678064=z{<>?6=4<{<4;34<35776;<770?4ak2wx:il50;0x93be2;lh708?1;3;7>{t>:81<7?k{<407?4ak27><<4>859>15e=919018>k:0:0?836j3;3863:1e82<1=:=8o1=5:4=43e>4>334;1k00:4<5252g95=4<5<9:6<6<;<70=?7?927>jh4<0g9>114=918018>=:0:7?804=3;3<63:2d82<7=:=;l1=5:4=5d6>4>334<>n7?72:?51=<60;16:=:5193890`c2829708k9;3;0>{t>mk1<77`d344>634?2:7?71:?6=1<6081694<5193890?7282:70;7e;3;5>;20j0:4<5259695=7<5<2;6<6;;<46f?4a>2wx:i850;gx90bc203018jj:8;890c6203018k=:8;890c4203018k;:8;890c2203018k9:8;890c0203018k7:8;890ba203018k?:8;890c>2h801;j7:3d5?xu1;90;6?u25569e7=:=ol1>k84}r606?6=jr7=454n2:?65<<48o168><52ga8913f282870::8;3;7>;3190:4?5243395=5<5:i=6<6=;<60b?7?;27?8>4>859>06g=91>0q~879;296~;10009jn5244195=754z?6064=f79>20?=91901;>;:0:7?xu3>l0;6?u247g96ce<5<>:6<6>;|q5<=<72:q6:5652ga8915>282870:<8;3;6>{t7`d34??=7?72:p03`=838p1989:6a8910a2;lh7p}93583>7}:>:91m?5262796c054z\5b<=:;|q5b2<72:qU:k94=545>`0<5??=6?h9;|q5b3<72:qU:k84=545>`3<5??>6?h9;|q5b0<72:qU:k;4=545>`2<5???6?h9;|q5b1<72`5<5??86?h9;<6be?7?:27?h<4>839~w3`4290=wS8i3:?7230g1=918019om:0:1?82c:3;3>6s|6g094?0|V?l970:96;f7?802938m:63;b782<7=:4>53ty=j<4?:6y]2c7<5=<=6n74=773>7`134>h?7?72:?7`1<60;168o;5190891gc28297p}9e683>2}Y>l=01989:6`891d>282:70:mb;3;0>;3jj0:4<5249495=4<5?>m6?h9;|q5a0<72>qU:h;4=545>2g<5=h26<6=;<6af?7?:27?nn4>839>0=0=91901;:l:3d5?xu1m=0;6:uQ6d689101212019l6:0:0?82ej3;3=63;bb82<6=:>=31>k84=5`g>4>63ty=i>4?:2y]2`5<5=<=6594=767>7`13ty=i?4?:5y]2`4<5=<=6584=760>7`134>im7?74:p2`7=83;?wS8j1:?723809>0=d=91;01;=k:3d5?82>83;3?63;8982<7=:4>434>o87?73:?7f0<60:168o85191891d0282870:na;3;7>;3ik0:4>524`a95=5<5=ko6<6<;<6g5?7?;27?h?4>829>0a5=9190q~8j0;2953}Y>l:01989:96891>>2829708<9;0e2>;30j0:4>5248295=2<5=3?6<6;;<6;839>0f5=91>019j;:0:7?82?l3;3863;b482<1=:4>334>jm7?74:?7eg<60=168lm5196891gc282?70:k1;3;0>;3l;0:49524e195=25dz\5`c=:5249a95=4<5?9=6?h9;<6;5?4al27?454>809>0gd=919019ll:0:7?820m3;3=63;7b82<4=:<1k1=5=4=5:g>4>534>ij7?74:p25>=839pR;>7;<7bg?4ak27>9i4>809~w3612908wS8?6:?6eg<5nj1699951938yv0693:1?vP9109>1g2=:oi018;6:0:2?xu1990;6>uQ602890d42;lh70;:7;3;5>{t>9l1<7=t^72e?83e:38mo63:5482<4=z{?:n6=4<{_43a>;2j809jn5254195=753z\54a=:=k:1>km4=472>4>63ty=n:180[07i27>mi4=fb9>11d=91;0q~8?9;297~X180169lo52ga8902>282:7p}90483>1}Y>9?018o6:3d`?83?<3;3>63:5`82<5=z{?;i6=4=9z\55g=:=9;1=5<4=42`>4>634?;h7?71:?65g<60:169f;3;7>;1:80:4<524ga95=7<5=nh6<6<;<103?7?927==h4>809>170=919018<::0:0?80cl3;3=6397982<7=:>>?1=5?4=407>4>434?9m7?71:?7bg<608168k=5190891c5282:70:ja;13b>;3m>0:4<524dd95=7<5=>h6<6;;<6g839>0ag=91;019h6:0:1?82ai3;3?63:0382<7=:66a34?957=?f:?7`c<48o168hj531d8905f282?70=86;3;5>;1l00:4<5rs73:>5<5lrT==45250`95=4<5<;o6<6=;<72a?7?:27>=k4>839>277=91801>=8:0:0?82cj3;3>63:2482<4=:>mn1=5<4=75;>4>634<<97?72:?666<608169?m5193891`e2829708ia;3;7>;1nm0:4>524g195=5<5=o96<6<;<6f4?7?:27?i94>829>0`3=91>019k8:0:1?82bn3;3>63:0482<4=:<=i1=5?4=73`>4>334?:<7?71:?7`<<60816:=>5190893452829708=3;3;6>;2800:4<5251c95=7<5<:?6>>i;<726?57n27>0c1=91>019k7:0:2?835?3;3863;eb82<6=:=:k1=5?4=40e>4>5349<:7?72:?5`<<60:1v;?7:181=~X191168h8519089365282:70;=b;3;5>;3nj0:4?524ea95=7<5<:=6<6>;<72>?4>859>177=91901863:2782<4=:>mo1=5=4=755>4>334?987?71:?66f<60;168kj5191891`b282:70:j3;3;5>;3m=0:4?524d795=5<5:=96<6<;<6fb?7?;27?h54>859>24`=91>01;66a34?;57?72:?64d<60:169==519089076282870;?e;3;0>;3m10:4?5253595=7<5=no6<6=;<6ga?7?;27?in4>809~w3702909mvP9169>0`0=91;01;>=:0:1?835j3;3>63;fb82<6=:4>534?:47?73:?667<60;169??519389047282970;=6;3;0>;1ll0:4<5266495=7<5<886<6=;<71g?7?;27?ji4>839>0cc=91>019k<:0:7?82b<3;3863;e482<4=:4>634>nj7?74:?7`=<60816:5;3;6>;3n=0:4>524ec95=5<5=lj6<6>;<73=?7?<27>839>155=91>018?>:0:1?837m3;3=63;f682<7=:4>534>oh7?73:?7``<60=168hm51908yv06>3:1>5uQ60489365282870;=b;3;7>;3lk0:4<5251495=5<5<;36<6>;<716?7?927>><4>859>176=91>01;?j:0:0?835>3;3>639de82<6=:>><1=5<4=407>4>334?9o7?74:?7ba<60=168kk5191893`e282?70:j3;3;7>;3m90:49524d`975`<5:=96<6=;<6fa?7?:27==k4>839>276=918018?::0:2?82a<3;3>63;d882<7=:4>434<9>7?73:?64<<60:169=o519689064282870;>1;3;5>;28l0:4?5253595=5<5=no6<6>;<6ga?7?:27?in4>859~w37229095vP9149>0ad=91>018>9:0:7?83603;3>63:2382<6=:=;;1=5<4=403>4>434;3nl0:4?526g`95=4<5=o86<6=;<6f0?7?927?i84>839>0`c=919018>::0:1?82a=3;3>639c182<7=:4>434?:97?74:?7b1<60=169<>5191891bf282?70:i9;3;7>;1890:495263095=2<5?886<6>;<73<>4>809>147=91>018>j:0:0?82a?3;3?63;e982<1=:=;21=5?4=5ff>4>634?8m7?73:?5`<<60;1v;h?:181[0a827:j?4>809~w3cb2909wS8je:?2b4<6081v;kk:181[0bl27:j=4>809~w3cd2909wS8jc:?2ac<6081v;km:181[0bj27:ih4>809~w3cf2909wS8ja:?2aa<6081v;k6:181[0b127:in4>809~w3c?2909wS8j8:?2ag<6081v98n:181821>3ii70:9a;0eg>{tfg<5=<26?hl;|q72=<72;q68;85e89>03>=:oi0q~:97;296~;3>?0n463;6681bf=z{:<36=48{<104?4a?27?:;48d:?6007}:52z?723444>839~w3b22909w0:96;320>;21m0:4?5rs7f7>5<5s4>=:7?>3:?6=g<60;1v;j<:180821>3;:>63>f`82<6=:=031=5<4}r4g6?6=;r7?:;4>109>5c?=91901878:0:1?xu1l80;6>u24749546<58l36<6<;<7:1?7?:2wx:i>50;1x910128:m70?i7;3;7>;21:0:4?5rs7ae>5<4s4>=:7??e:?2b3<60:1694?51908yv0dm3:1?v3;67824d=:9o?1=5=4=4:e>4>53ty=oi4?:2y>030=no16=k:5191890>c28297p}9c`83>6}:;|q6b7<72:q68;856b9>1cd=:oi018m8:0:2?xu2n80;69u247492g=:=ok1>km4=4`f>d1<5;|q6b5<72=q68;856`9>1c?=:oi018lk:`5890e2282:7p}:eg83>1}:4>63ty>ih4?:5y>030=?>169k952ga890de2h=018m<:0:2?xu2mm0;69u2474933=:=o<1>km4=4`b>d1<5;|q6af<72=q68;85749>1c3=:oi018l6:`5890e6282:7p}:ec83>1}:4>63ty>il4?:5y>030=?:169k=52ga890d02h=018li:0:2?xu2>h0;6?u256596ce<5?3>6<6;;|q62<<72;q69:852ga893?5282?7p}:7283>7}:=>l1>km4=7a5>4>33ty>;?4?:3y>12c=:oi01;m<:0:7?xu2?80;6?u256f96ce<5?hm6<6=;|q635<72;q69:m52ga893d>28297p}:6g83>7}:=>h1>km4=7`0>4>53ty>:h4?:3y>12g=:oi01;ok:0:1?xu2>m0;6?u256;96ce<5?k<6<6=;|q62f<72;q69:652ga893g628297p}:6c83>7}:=>?1>km4=7;a>4>53ty>:54?:3y>122=:oi01;6j:0:1?xu11=0;6?u25d29e7=:>0<1>k84}r4:5?6=:r7>hk4n2:?5=6<5n?1v;m::18183b03k9708l7;0e2>{t>j81<7d4<5?i?6?h9;|q5fg<72;q69h85a39>2ge=:o<0q~8m5;296~;2m<0j>639b781b3=z{?km6=4={<7f0?g5347}:=l81m?526`696c052z?6a4038m:6s|69c94?4|57`13ty==94?:cy]242<5:>>6<6=;<1fe?7?:27=8i4>829>21c=91>01>8<:0:0?851<3;386399782<7=:><=1=5?4=4:a>4>634>:j7?72:p245=83hpR;?<;<462?7?;2788>4>839>7ae=918019?>:0:1?852n3;3?63<6182<1=:>=k1=5=4=76a>4>334<2?7?72:?6<<<6081v;829>717=91801>mj:0:1?827;3;3>6394682<6=:>=21=5:4=27a>4>4349>o7?74:?5g2<60;1694j51938yv05j3:1mvP92c9>202=91901>=i:0:1?85a=3;3>63<5682<6=:;<21=5:4=7a7>4>534uQ63c8961028>=70=88;372>;4?00:8;5236a9510<5:=j6<:9;<14f?73>278;i4>479>72c=9=<01>=k:0:1?85b?3;3>639be82<6=:>ko1=5=4=762>4>4347?74:?016<60:16?8:519689334282:70;69;3;5>{t>;31<7?;{_41=>;4?>0:885236:9513<5:=26<::;<14g?73=278;l4>449>72d=9=?01>9k:066?850m3;?963<3c82<7=:;m31=5<4=537>4>534;21>0:4<5262d95=7<5?>;6<6=;|q56=<728>pR;<7;<143?73<278;54>459>72?=9=>01>9l:067?850i3;?863<7c8201=:;>n1=9:4=25f>423349857?72:?0gg<60;168=85190893d62828708m2;3;7>;45235a95=2<5??:6<6>;<40g?7?:27>584>809>26d=91;0q~8=7;2956}Y>;=01>98:060?85003;??63<788206=:;>i1=9=4=25b>424349;1ik0:4>526`a95=5<5:><6<6<;<17809>1<5=91;01;=8:0:2?80403;3>6s|67194?g|5:=n6>?=;<171?7?;278il4>859>2ge=;9l01;:k:0:2?803m3;3=63<6282<4=:;?>1=5?4=774>4>434>:j7?74:p234=83kp1>9k:231?802>3;3>63<4282<6=:;mi1=5:4=532>4>33451938932f282:708;b;3;5>{t>?;1<7ot=25`>67534<>97?72:?004<60:16?nk519689164282?708m0;13b>;1<>0:4<5265:95=7<5:?i6<6>;<16g?7?92wx:;>50;;x961e2:;9708:4;3;6>;4;o0:4>523g795=2<5?kj6>>i;<163?7?9278954>809>210=91>01;:::0:7?xu1=o0;64u236c9744<5:9o6<6<;<1f3?7?<27=m94<0g9>217=91;01;:=:0:2?852;3;3=63<5582<4=:><91=5=4}r46a?6=ir78;44<139>76d=91901>j6:0:7?826<3;386399d804c=:;=l1=5?4=273>4>634<>>7?73:?57c<60=16:9>51968yv02l3:1mv3<798057=:;:31=5=4=2aa>4>334>;:7?74:?5==<48o16?9l51938962d282:708:1;3;7>;1;j0:495262`95=2o7>59z?032<49;16?>85191896`?282?7087b;13b>;4<>0:4<5235:95=7<5??;6<6<;<403?7?<27=?54>859~w30e2908w0=8e;376>;153z?03a<6<;16?;?531d8932d2::m7p}96883>6}:;>i1=9<4=76:>66a349>h7=?f:p23>=83>p1>9m:061?803<3;3=63<58804c=:439>215=;9l01>;::22e?xu1>?0;6;u236;9514<5?9o6<6>;<6:1?7?927=?h4>809>707=;9l0197<:0:1?xu1><0;69u236:9514<5?926<6>;<40e?7?92788i4<0g9~w303290=w0=87;376>;1;?0:4<524`:95=7<5=k26<6>;<6aa?7?9278844<0g9~w6232903w0=77;c4?853=38m:63;3782<7=:<;=1=5<4=50;>4>43492<7?73:?0fc<60=168<=51968yv53:3:1:v3<878b3>;4<:09j;5243495=4<5=;>6<6;;<1;b?7?;27?<84>859~w627290=w0=75;c4?853938m:63;0682<1=:;1o1=5=4=2d4>4>334>:?7?73:p76c=83=p1>6;:`58965a2;l=70=i9;3;0>;40m0:4>523d;95=5<5=:>6<6<;<1`5?7?;2wx?>m50;5x96>42h=01>=k:3d5?85bj3;3863<8b82<6=:;mh1=5=4=2d4>4>434>987?73:p76g=836=:`58965e2;l=70=kd;3;0>;40k0:4>523bf95=2<5:o26<6;;|q07=<72?q6?5?5a69>76?=:o<01>mi:0:7?85?i3;3?63;4km0:4>5243695=2<5=9<6<6;;|q027<72=q68?85196896022;l=70=60;3;0>;3:90:4<5rs27f>5<3s49==71}:;k84=527>4>33493i7?74:?74=<60:1v>;9:187852138m:634>43ty89?4?:5y>703=:o<01>k7:0:7?85?k3;3863n6=4;{<165?4a>278hl4>859>7=d=91>01>jj:0:0?xu4829~w621290>w0=l6;3;0>;4<009j;5239;95=2<5:i96<6;;<1`1?7?<2wx8:o50;0x91>42;lh70876;3;7>{t<>31<77`d34<3>7?73:p02>=839p1;6;:0:0?80?83;3?63;8081bf=z{==<6=4={<6;4?4ak27=;h4>829~w1112909w0:8f;0eg>;1?j0:4>5rs556>5<5s4<6=4={<4;2?4a>27:j?4>829~w3>42909w0874;0e2>;6n80:4>5rs7:2>5<5s4<3>7eg82<6=z{?=o6=4={<44a?4a>27:ih4>829~w31e2909w088c;0e2>;6mm0:4>5rs75:>5<5s4<ec82<6=z{:h96=4<{<3ee?7?:278nl4=fb9>006=;9l0q~=m1;297~;6n00:4?523c;96ce<5=>m6<6<;|q0f5<72:q6=k65190896d?2;lh70:;f;3;0>{t;hl1<7=t=0d4>4>5349i;7oj:18087a>3;3>63839>7g3=:oi019;>:0:0?xu4ij0;6>u21g695=4<5:h?6?hl;<665?7?<2wx?ll50;1x94`4282970=m3;0eg>;35<5s4>829~w1172909w0:80;0eg>;1k:0:4>5rs253>5<5s4>=:7?<4:?5<3<60=1v>8i:181821>3;8?6398582<1=z{:859~w60c2909w0:96;305>;1090:495rs24`>5<5s4>=:7?<0:?53`<60=1v>8m:181821>3;9o6397b82<1=z{:859~w60>2909w0:96;322>;1?>0:495rs4f0>5<5s4?n<7i:4=fb9>030=k>1v8jn:18183b>38mo63;678`2>{t=m31<77`d34>=:7m:;|q6`=<72;q69h:52ga891012j>0q~;k7;296~;2m:09jn524749g6=z{:3d`?821>3hn7p}:d583>7}:=mo1>km4=545>g552z?6`a<5nj168;85a99~w341290hwS8=6:?032<2l278;54:d:?03<<2l278;n4:d:?03d<2l278;o4:d:?03a<2l278;h4:d:?5e0<60:16:l85191890?6282:7p}92483>f}Y>;?01>98:4`8961?296:4`8961d29n:4`8961e29k:4`8961b2;4?>0>m63<7986e>;4?00>m63<7b86e>;4?h0>m63<7c86e>;4?m0>m63<7d86e>;1100:4>5268c95=5<5<2o6<6>;|q557<72jqU:<<4=254>0?<5:=36874=25:>0?<5:=h6874=25b>0?<5:=i6874=25g>0?<5:=n6874=7:`>4>434<3h7?73:?6<0<60:1v;9<:181850m3k970?ja;0e2>{t>>81<7d4<58o26?h9;|q534<72;q6?:m5a39>5`>=:o<0q~880;296~;4?k0j>63>e681b3=z{?96:`0894c22;l=7p}96e83>7}:;>21m?521d696c052z?0324=f79~w0`d290jw0;i3;;:?83a<33270;i5;;:?83a>33270;i7;;:?83a033270;i9;;:?83ai33270;ib;;:?83ak38m:6s|52194?4|5<996l<4=413>7`13ty>?k4?:5y>16`=:oi018=j:0:7?833839;j63:3c82<4=z{<996=4<{<706?4ak27>?i4>839>117=91>0q~;;0;296~;2;o0j>63:4181b3=z{<9o6=4={<70g?g534?8h7a}:=:=1>km4=415>4>434?mj7?72:?546<60;16:n751918905b282:70;<1;3;6>;2;00:4?5261395=4<5<>96<6>;<46f?7?927=954>809>1cb=91;0q~;<4;29f~;2;=09jn5252495=4<5839>16c=919018=>:0:2?80793;3=63:4382<6=:=:h1?=h4=4:6>4>63ty8<;4?:3y>1c5=i;169n652g48yv57?3:1>v3:f58b6>;2k009j;5rs22;>5<5s4?m97o=;<7`e?4a>2wx?=750;0x90`12h8018mm:3d5?xu48h0;6?u25g59e7=:=ji1>k84}r13f?6=:r7>j54n2:?6ga<5n?1v>>l:18183a13k970;le;0e2>{t;9n1<7d4<51a6=:o<0q~:k7;2964}:;;l1=:k4=545>3b<5=<=6ll4=545>de<5=<=6lj4=545>dc<5=<=6nm4=545>fb<5=<=6nk4=545>f`<5=<=6ho4=545>`d<5=<=6hh4=545>c6<5=<=6>>;;<652?57=27?:;4<149>030=;8<018:::8a8902?2h=018:n:`58902d2h=018:j:`5890372h=018;=:`5890332h=018;9:`58903?2h=018:9:`589063282970:j9;3;5>;3mm0:4?5244295=453z?7`g<5n?1689=51908915f28297p}=e`83>4g|5=9h6<6<;<617?7?:278o=4>859>7f1=91>019:j:0:1?82b:38m:63;5`82<7=:<<21=5?4=506>4>4349347?73:?77`<60:168>j51938913c282:70::c;3;5>;3;<0:4?523cf975`<5=>;6<6>;<1;=?7?:2784l4>839>7=d=91801>6l:0:1?85?l3;3>63<8d82<7=:;1l1=5<4=2;3>4>534>8;7?71:p6`c=83;hw0:;3::0:4<523b295=5<5:i<6<6>;<67a?7?;27?io4=f79>00g=91>019;7:0:7?85dn3;3>634>534>;;7?72:?750<60;168>h519089146282970:;4k:0:4?5245395=4<5=>96<6>;<601?7?<278o84>839>7f0=91;019<6:22e?85em3;3=631=5?4=51b>4>63ty:jk4?:32x915d282970:=3;3;7>;4k90:4<523b595=5<5=>n6<6;;<6e7?4a>278h<4>809>073=918019=j:0:7?85d;3;3?63;4082<4=:;j>1?=h4=504>4>334>947?71:?0gc<60816?ij5193896ce282:70=i9;3;5>;38>0:4<5240795=7<5=9m6<6>;<677?7?927??o4>809>074=918019?8:0:1?82713;3>634>5349ii7?72:?0fc<608168>o51918yv2an3:1?v3:0781b3=:>on1=5:4=426>4>33ty><:4?:2y>143=:o<018??:0:1?835n3;3?6s|26f94??|5:=<6>?l;<1472e=;8i01>9n:23`?850j39:o63<7e805f=:;>o1?7`13ty>=>4?:3y>14`=91;018?7:3d5?xu29=0;6?u250g95=7<5<8;6?h9;|q653<72;q697}:=8h1=5?4=401>7`13ty9n>4?:by>7g5=1016?o:5989>7g3=1016?o85989>7g1=1016?o65989>7g?=1016?oo5989>173=:o<019;<:22e?82413;3>63;3982<4=z{;i;6=4<{<7a3??d34?h477l;<4g3?4a>2wx>n;50;1x90d02::m70;l8;3g0>;2jo09j;5rs4`4>5<4s4?i;7k27>o446c:p6f0=839p18l7:22e?83d13;o863:c181b3=z{27>n446c:?6gd<>k2wx>n950;1x90d>2::m70;la;3g0>;2k809j;5rs4`:>5<4s4?i57k27>oo46c:p6f>=839p18ln:22e?83dj3;o863:c381b3=z{27>no46c:?6gf<>k2wx>n750;1x90de2::m70;lc;3g0>;2k:09j;5rs4`a>5<4s4?in7k27>oi46c:p6fd=839p18ll:22e?83dl3;o863:c581b3=z{27>ni46c:?6g`<>k2wx>nm50;1x90dc2::m70;le;3g0>;2k<09j;5rs4`g>5<4s4?ih7k27>ok46c:p6fc=839p18lj:22e?83dn3;o863:c781b3=z{27>h=46c:p6f`=838p18j?:0f7?83d?38m:6s|2`:94?4|58lj6?h9;<3fe?7?92wx>5650;0x94`52;l=70?ja;3;6>{t::i1<77`134;n57?71:p65c=838p1:3d5?87b13;3>6s|21c94?4|58l36?h9;<3f==50;0x94`72;l=70?j8;3;6>{t:9:1<77`134;n;7?71:p6c7=838p16s|2dd94?4|58l=6?h9;<3f2?7?92wx>hl50;0x94cb2;l=70?j6;3;6>{t:l91<77`134;n97?71:p6a0=838p16s|2e394?4|58l?6?h9;<3f0?7?92wx>n?50;0x94cd2;l=70?j4;3;6>{t:k>1<77`134;n?7?71:p5cc=838p16s|2b094?4|5<:;6<6>;<736?4a>2wx>o;50;0x90662;l=70;?0;3;6>{t:981<74>634?;97>:0:0?837<38m:6s|22d94?5|5<:;6?h9;<7a2?7?:27>4=4>829~w7b?2909w0;?d;0e2>;28k0:4<5rs3f1>5<5s4?;h7?74:?64=<5n?1v?m<:181837l3;3>63:1381b3=z{;h=6=4={<73g?4a>27>839~w7612909w0;?c;3;0>;29909j;5rs0d`>5<5s4?;o7?72:?64c<5n?1v8?l:181836k38m:63:1882<4=z{;n86=4={<72b?4a>27>=n4>809~w7e32909w0;>e;0e2>;29j0:4?5rs43b>5<5s4?:m727>=l4>839~w7g>2909;0e2>;20:0:4?526e`96cb<5?nj6?hk;<46=?7?<27=9o4>829>20>=91>0q~52z?66`<5n?169?j51908yv06l3:1>v391b81b3=:=;o1=5?4}r0ab?6==r7>>i4=f79>2cb=91;01>9>:0:0?82en3;3>63<7782<1=z{;h96=46{<717?4a>27=9;4>809>203=91;01;;;:0:2?802;3;3>6395382<7=:><;1=5<4=773>4>534<>;7?72:p6`e=83>p19jl:3d5?80aj3;3=639fe82<7=:q6?>952g489622282:70=;3;3;5>;4<80:4<5232d95=7<5:9o6<6>;<10f?7?9278?44>809>760=91;01>mj:0:2?85dj3;3=634>6349n;7?71:?0b=<60816?k;519389161282:70:?3;3;5>;39=0:4<5240395=7<5=on6<6;;<62b?7?92wx>>950;;x93122;l=70876;3;6>;10=0:4?5269095=4<5?2;6<6=;<44a?7?:27=;n4>839>22g=91801;98:0:1?xu51:0;6lu266:96c0<5?2=6<6>;<4;0?7?927=4?4>809>2=6=91;01;9j:0:2?800k3;3=6397`82<4=:>>=1=5?4=5`e>4>43ty9;136<6=;<47e?7?:27=8o4>839>217=91801;:=:0:1?804k3;3?6394782<6=:>:=1=5=4=71;>4>434<8j7?73:?505<60:16:>l51918932228287p}=0883>47|5=l=6?h9;<47`?7?<27=8h4>829>211=91>01;:7:0:0?803i3;386394c82<6=:>=;1=5:4=761>4>434<8o7?71:?503<60816:>951908935?282:708;1<90:4<5262`95=4<5?>>6<6=;|q1`g<72=q68k75193891`f282?70:i8;0e2>;4?80:4?5rs3`f>5<4s4>n:7;<4aa?7?:27=n:4>809>2g>=91801;l>:0:2?80e:3;3>639ac82<4=:>hi1=5<4=7c6>4>6345190893?>282:7086a;3;6>;10j0:4<5269f95=4<5?i<6>>i;<4`0?57n27=5;4<0g9>2<5=;9l0q~hj50;6x93462;l=708l0;3;5>;3n<0:4>5261695=551cy>254=:o<01;j7:0:1?83en3;3>639c182<1=:=j:1=5:4=4a2>4>334?h>7?74:?6g6<60=169n:5196890e2282?70;l6;3;0>;1l>0:4<525b595=2<5<;;6<6;;<4`2?7?:27=o>4>839>2<3=91801;7=:0:1?80en3;3=639b882<4=:>k91=5?4=7cg>4>634b282:708?4;3;6>{t:9l1<7jt=4d`>4>6345190890e6282970;l2;3;6>;2k:0:4?525b695=4<56<6=;<7`2?7?:27=h:4>839>1f1=918018hj:3d5?xu6nm0;6ou259;95=5<5<3o6<6<;<7:f?7?;27>544>829>1<1=9190187::0:0?83>;3;3?63:9082<6=:=1l1=5=4=77:>7`134?3h7?73:p613=83ip187k:0:7?83>j3;3863:9882<1=:=0=1=5:4=4;6>4>334?2?7?74:?6=4<60=1695h5196890>e282?70;75;3;0>;20m0:495264:96c054z?6bf<60:16:875190890>2282970;id;0e2>{t:ki1<7?8{<4gnk4>859>1f6=919018m>:0:0?83d:3;3?63:c282<6=:=j>1=5=4=4a6>4>434?h:7?73:?5`2<60:169n95191893e1282:708l3;3;5>;11<0:4<5268095=7<5?hm6<6<;<4a7?7?;27=mi4>829>2d1=91901;o>:0:0?80>j3;3?6398d82<6=:>m31>k84}r03f?6=?r7>>o4=f79>761=918019h<:0:2?837=3;3?6392282<6=:=:k1=5<4=5d6>4>63ty9<<4?:7y>1ce=9180186<:0:7?80cj3k970:i5;0e2>;1=00:4<5264:95=5510y>17?=:o<01>8<:0:7?851<3;3?63<5g82<1=:;?:1=5=4=27a>4>3349>o7?73:?012<60=16?86519189634282?70=:4;3;7>;4i6<6;;<17g?7?;2788:4>859>71>=9190q~k84=240>4>5349=87?72:?01c<60;16?;>51908963e282970=:c;3;6>;4=>0:4?5234:95=4<5:?86<6=;<160?7?:2788k4>839>706=91801>:m:0:1?853k3;3>63<4682<7=:;=21=5<4}r0f1?6=;r7?i?4>859>0`1=91>019k6:3d5?xu2954=f79>110=1j1698l59b9~w0312908w0;:6;0e2>;2=102o63:678:g>{t=<>1<7=t=477>7`134?>:77l;<751??d3ty>9?4?:2y>104=:o<018;;:8a8900320i0q~;:0;297~;2=909j;525409=f=:=?915n5rs46f>5<4s4??i7k27>:?46c:p11e=839p18:l:3d5?833m33h70;91;;`?xu2u255c96c0<5<>h64m4=443>53z?60=<5n?1699o59b9>10`=1j1v8:::180833=38m:63:498:g>;2=l02o6s|57594?4|5<>>6>>i;<76e?4a>2wx95?50;fx90132030189::8;8901?20301896:8;8901f2030189m:8;8901d2030189k:8;8901b2030189i:8;8901120301898:8;890>72;l=7p}:8383>6}:=>>1m?525`;9e7=:=1>1>k84}r7;g?6=;r7>;84n2:?6ed4n4=f79~w0>b2908w0;88;c1?83fl3k970;7e;0e2>{t=0:1<7=t=45:>d4<57`13ty>5?4?:2y>12g=i;169lh5a39>1<4=:o<0q~;64;297~;2?k0j>63:b18b6>;21=09j;5rs4;5>5<4s4?=839p189k:`0890d52h801877:3d5?xu21h0;6>u256g9e7=:=k91m?5258c96c053z?63cn94n2:?6=f<5n?1v867:180830>3k970;nb;c1?83?038m:6s|59c94?5|5<=<6l<4=4c`>d4<5<2j6?h9;|q6e5<72;q698k52g4890>d28297p}:a083>7}:=k84=4:f>4>53ty>m?4?:3y>136=:o<0187?:0:1?xu2i:0;6?u257396c0<5<396<6=;|q6e1<72;q69;<52g4890?328297p}:a483>7}:=?91>k84=4;5>4>53ty>m;4?:3y>132=:o<01877:0:1?xu2i>0;6?u257796c0<5<3j6<6=;|q6e=<72;q69;852g4890?d28297p}:9d83>7}:=

k84=4:;>4>53ty>5k4?:3y>10e=:o<0186n:0:1?xu2j<0;6iu25`;9=<=:=hk154525`f9=<=:=ho154525`d9=<=:=k:154525c39=<=:=k8154525c19=<=:=k>154525``9=<=:=hi154525c496c0o97>52z?7f1<>127?h;4=f79~w1e2290>w0:80;c1?82d138mo63;9282<4=:1=5?4=5ab>4>63ty?o;4?:4y>027=i;168nl52ga891>a282970:lc;3;5>;3l:0:4<5rs5a4>5<2s4><>7o=;<6``?4ak27?oh4>809>0=b=91;019j=:0:2?xu3k10;68u24619e7=:km4=5f3>4>634>3m7?71:?7`4<6081v97l:186821?3k970:n0;0eg>;3i80:4<5248595=7<5=ko6<6>;|q7=a<720d4=:oi0197?:0:2?82f;3;3=63;ab82<4=z{=3n6=4:{<65=?g534>j870}:;<6;e?7?:27?ml4>809~w1>e2909w0:8f;c1?82?j38m:6s|49;94?4|5=2;6l<4=5::>7`13ty?4:4?:3y>0=4=i;1685652g48yv2?=3:19v3;828b6>;3080j>63;7d82<6=:<1<1>k84=55`>4>43ty?n94?:3y>0g2=:oi0198j:`08yv2e83:19v3;6b8b6>;31=0:4<524c296ce<5=h:6<6>;<6a1?7?92wx85:50;3282e138m:63;8882<1=:<1h1=5:4=5:;>4>334>h<7?74:?7g1<60=168o?5196891d4282?70:nf;3;0>;3i>0:49524`795=2<5=k86<6;;<6b5?7?<27?h=4>859>0fc=91>019ml:0:7?82di3;386s|4c:94?4|5=h?6l<4=5a3>7`13ty?n?4?:4y>03b=i;168o<52ga891d4282:70:7f;3;5>;3j?0:4<5rs5cf>5<2s4>=n7o=;<6ba?4ak27?4n4>809>0d`=91;019l8:0:2?xu3k80;68u247d9e7=:km4=5;6>4>534>h?7?71:?7g1<6081v>7m:180823m38m:63;4g82<4=:<<81=5:4}r1b5?6=?r7??n4=f79>7fb=91801>jm:0:1?85b13;3>634>53ty8m=4?:9y>7f6=:o<01>mj:0:0?85ck3;3?634>434>:87?73:?0g4<60;1v>o;:18b85d?38m:634>3349o<7?71:?0``<60816?hm5193896`f282:70:?8;3;5>;39?0:4<5rs2c0>5<>s49hn7?73:?0`<<60:16?h95191896`2282870:?3;3;7>;3980:4>523b196c0<5:i96<6>;<62b?7?;2wx?l;50;`x915c2;l=70=l6;3;7>;3:>0:4<5243:95=4<5:im6<6<;<1g`?7?;278io4>829>7c?=919019>8:0:0?826=3;3?6327?>;4>809>060=91901>mk:0:2?85cj3;3=634>634>:?7?71:p7j>:0:1?824=38m:63;3882<4=:<;81=5?4=534>4>634>;57?71:?0bg<60816?hj5193896ba282:7p}<8683>7}:;1=1>k84=2;:>53z?0<2<48o16?4651e6896?72;l=7p}<8783>6}:;1<1>k84=2:4>7<1=9m>01>6i:3d5?xu40<0;6>u239796c0<5:2=64m4=2;4>53z?0<0<48o16?4851e6896>b2;l=7p}<8583>6}:;1>1>k84=2:6>7<3=9m>01>6k:3d5?xu40:0;6>u239196c0<5:2?64m4=2;6>53z?0<6<48o16?4:51e6896>d2;l=7p}<8383>6}:;181>k84=2:0>7<5=9m>01>6m:3d5?xu4080;6>u239396c0<5:2964m4=2;0>53z?0<4<48o16?4<51e6896>f2;l=7p}<8183>6}:;1:1>k84=2:2>7<7=9m>01>66:3d5?xu4?o0;6>u236d96c0<5:2;64m4=2;2>52z?03c<48o16?5652g48yv2213:1>v3;5`81b3=:;121=5<4}r663?6=;r78;k4n7:?71=<5n?16?5651938yv5ej3:1>v3;4jj09j;5rs2ab>5<5s49i87o=;<1g5?4a>2wx?i650;0x96d22h801>ji:3d5?xu4m?0;6?u23c49e7=:;ln1>k84}r1e0?6=:r78n:4n2:?0bg<5n?1v9>=:18185e03k970:?9;0e2>{t<8:1<7d4<5=;<6?h9;|q75`<72;q6?oo5a39>074=:o<0q~::e;296~;41809j;523ca95=4>j7>52z?0=7<5n?16?i?51918yv2183:1>v3<9281b3=:;ml1=5:4}r655?6=:r78594=f79>7`b=91>0q~:92;296~;41<09j;523g`95=2=?7>52z?0=3<5n?168=751968yv21<3:1>v3<9681b3=:<8=1=5:4}r651?6=:r78554=f79>074=91>0q~::b;296~;4?o02o63;5b81b3=z{=>i6=4<{<607??>34>8>776;<67g?4a>2wx88850;0x96?>2;l=70:{t<=n1<7d4<5=?86?h9;|q771<72;q68><5a39>06d=:o<0q~53z?663<5n?169?;51908912d28297p}=d183>7}:>mo1>k84=7fg>4>33ty9h94?:5y>220=:o<01;9::0:0?80003;3?63<7782<6=z{;n>6=4={<710?4a>27>>>4>829~w7b>2908w0;=c;0e2>;2:h0:4>5253:95=452z?7ba<5n?168kl51968yv4cl3:1>v3;fd81b3=:2cg=91>0q~4>634;m97?71:?2b3<60816=k95193894`?282:70?i9;3;5>;6nh0:4<524e;96c0<58l96<6=;<3e5?7?:27:j=4>839>5``=9180163>eb82<7=:9lh1=5<4}r0e6?6=:r7?j>4>859>0c2=:o<0q~n=7>52z?7a5<608168ih52g48yv46m3:15v3;e181b3=:9l91?=h4=0g7>66a34;n97=?f:?2a3<48o16=h9531d894c?2::m70?j9;13b>;6mh085m<7?71:?764<608168>j5190896e4282?70:;1;3;7>;3<;0:4?5244f95=4<5=?h6<6=;<601?7?;27?ii4=f79~w1`5290jw0:i0;3;6>;3ml09j;5243395=2<5=9o6<6<;<1`7?7?927?8<4>859>014=919019;k:0:0?822k3;3?63;3482<4=z{;ko6=4>6z?7b5<5n?168>m519389144282?70=l0;3;6>;4k>0:4?5245g95=7<5=?j6<6>;<66839>7=>=91>019=j:0:1?85en3;3>63<8882<4=:;1k1=5?4=2:a>4>63493o7?71:?0a282:70=60;3;5>;4jl0:4>5243695=452z?7a1<5n?168ho51908yv4fn3:1>v3;e481b3=:0`d=9180q~09j;524d`95=752z?037<5n?16?:?51938yv22=3:1>v3;5181b3=:<<81=5<4}r660?6=:r7?9<4=f79>004=91;0q~8l1;297~;1jo09j;526cf95=4<5?hn6<6;;|q5fd<72:q6:o752g4893d02829708m8;3;0>{t>k>1<7=t=7`0>7`134hi1=5:4}r4b2d3=91801;o9:0:7?xu1i;0;6>u26`396c0<5?3m6<6=;<4b4?7?<2wx:4m50;1x93?e2;l=70869;3;6>;11h0:495rs7:e>5<4s4<3i783:15v39c181b3=:>ko1=5?4=7`;>4>6347?71:?5ef<60816:l85193893g7282:7086a;3;5>;10m0:4<5rs3f4>5<5s4?mo7?74:?541<6l<1v?jn:18183?j38m:63:8`82<6=z{<2=6=4={<7;0?7?<27>484>d49~w0>02909w0;73;0e2>;20=0:4>5rs3ff>5<5s4>357?73:?7d49~w7c6290?w0:n8;3;7>;3i00:4>524cg95=5<5?9<6?h9;|q1a7<72=q6:>85191891g?282970:n9;3;6>;1;109j;5rs2a:>5<5s49ih7m7:18185ek3;3863859>0<5=91>01;=i:3d5?xu5m>0;69u262f95=5<5?9n6<6<;<6:7?7?;27=8=4=f79~w7c?2909w08<9;3;6>;1;k09j;5rs3g:>5<4s4<8o7o51918yv5c;3:1>v37fe=91;0q~=k6;296~;4kj0:4?523b`96c052z?0gf<5n?16?i>51968yv5c:3:1>v3859>7a6=9m?0q~=j1;296~;4lh0:4>523e`95a352z?0`f<5n?16?io51938yv5b<3:1>v3k84}r1f1?6=:r78hl4=f79>7ac=91>0q~=j0;296~;4lm09j;523eg95=47>52z?0`c<60:16?ik51e78yv5bn3:1>v37`>=9180q~=i2;296~;4m>09j;523d:95=752z?0a=<5n?16?hm51968yv5bm3:1>v3829>7`e=9m?0q~=id;296~;4n?0:4>523g595a352z?0b=<5n?16?k851938yv2783:1>v3k84}r635?6=:r78j;4=f79>7cg=91>0q~=ic;296~;4n009j;523gc95=452z?0bg<60:16?ko51e78yv27j3:1>v3;0582<6=:<9?1=i;4}r63`?6=:r7?<;4=f79>052=91;0q~:?e;296~;38=0:4?5241196c0;j7>52z?741<5n?168=651968yv27i3:1>v3;0681b3=:<921=5<4}r63g?6=:r7?<44>829>05>=9m?0q~:>9;296~;39;0:4>5240195a3:n7>52z?751<5n?168<<51938yv26k3:1>v3;1382<7=:<8;1>k84}r62`?6=:r7?=?4=f79>040=91>0q~:>8;296~;39<09j;5240495=4:m7>52z?752<60:168<851e78yv25i3:1>v3;2782<6=:<8l1=i;4}r604?6=:r7?>;4=f79>076=91>0q~:<1;296~;3:<0:4<5243396c09n7>52z?760<60=168?:51e78yv25k3:1>v3;2481b3=:<;:1=5<4}r61`?6=:r7?>44=f79>076=9190q~:=e;296~;3:;0:4>5243295a39j7>52z?77`<5n?16?om51938yv47<3:1>v394481b3=:212=919019ln:0:2?xu31;0;6?u246g95=2<5=2n652g48911b28297p};9983>7}:<091>k84=5;7>4>43ty?5l4?:3y>0<3=:o<0197;:0:1?xu31k0;6?u248696c0<5==h6<6=;|q7=<<72;q68:m5196891?128n>7p}=0b83>1}:<1<1=5?4=5`b>7`134>3i7?71:?7=3<6081v9:n:18182383;3?63;3`82`0=z{=>?6=4={<60b?4a>27?8=4>859~w1222909w0:;0;0e2>;3;?0:4<5rs565>5<5s4>?=736=4={<677?4a>27??:4>829~w12>2908w0:<6;0e2>;3;00:495242:95=553z?602<5n?16998531d8903e28n?7p}:5883>6}:=<31>k84=47;>66a34?=:7?k4:p101=839p18;8:3d5?832>39;j63:6482`1=z{6=4<{<761?4a>27>994<0g9>132=9m>0q~;:3;297~;2=:09j;52540975`<5<<86{t==l1<7=t=46e>7`134??i7=?f:?624<6l=1v8:k:180833l38m:63:4b804c=:=?:1=i:4}r77f?6=;r7>8o4=f79>11g=;9l018;i:0f7?xu2<00;6>u255;96c0<5<>36>>i;<76a?7c<2wx98j50;0x903c2;l=70;:c;3g0>{t:8:1<74b334>>h763;cb82<7=:7`134>h87?72:p644=83?p19o8:0:1?82f=3;3>63;a282<7=:7`13ty9=>4?:3y>0f4=i;168n:52g48yv46<3:1>v3;7e8b6>;3?l09j;5rs336>5<5s4>2wx><850;6x91db2;l=70:m1;3;6>;3j:0:4?524`d95=452z?7fg<5n?1685k51918yv4603:1>v3;bb81b3=:<0<1=5=4}r02=?6=:r7?n=4n2:?7f4<5n?1v??n:18182e:3k970:m3;0e2>{t:8h1<7d4<5=k<6?h9;|q15f<72;q68l:5a39>0d3=:o<0q~<>d;296~;3i;0j>63;a281b3=z{;;m6=4={<6b4?g534>j=77}:7>52z?7ga7`13ty9>84?:3y>0=0=91>019lk:0f6?xu5:?0;6?u242`95=4<5=936752g48915e28287p}=2983>7}:4b23ty9>44?:3y>0f5=:o<019m;:0:0?xu5:h0;6?u24c395=5<5=h>67p}=2b83>7}:4b23ty9>i4?:3y>0d1=919019on:0f6?xu5:l0;6?u24`795=5<5=ki67p}=3183>7}:4b23ty9?<4?:3y>0a6=919019j>:0f6?xu5;;0;6?u24bg95=5<5=n967p}=3583>7}:1>k84=5ab>4>43ty9?84?:3y>7f2=:o<01>ll:0:0?xu5;?0;6?u242495=2<5=9<6b28297p}=3883>7}:<0=1>k84=5;5>4>53ty9?l4?:3y>7f4=:o<01>m>:0:7?xu5;k0;6?u252;95=5<5<9i6?h9;|q17a<72;q68hh52g4891cb282:7p}=3d83>7}:=131>k84=4:;>4>43ty98=4?:3y>17}:=0=1>k84=4;5>4>43ty9894?:3y>1<3=:o<0187;:0:0?xu57}:=1l1>k84=4:f>4>43ty9844?:3y>1=e=9190186k:0f6?xu5282?7p}=4b83>7}:>8l1>k84=73`>4>43ty98i4?:3y>276=:o<01;?l:0:2?xu5o52g4891>a282?70:67;3;0>;3jm0:4>5rs71g>5<3s4<8i77}:>kn1>k84=7``>4>63ty99=4?:3y>2gc=:o<01;ll:0:1?xu5=80;6?u26c596c0<5?h=6<6>;|q117<72;q6:o652g4893d128297p}=5283>7}:>k;1>k84=7`3>4>63ty9994?:3y>2g4=:o<01;l?:0:1?xu5=<0;6?u26``96c0<5?kj6<6>;|q113<72;q6:lm52g4893gf28297p}=5683>7}:>h?1>k84=7c7>4>63ty9954?:3y>2d0=:o<01;o;:0:1?xu5=00;6?u268d96c0<5?3n6<6>;|q11d<72;q6:l>52g4893?b28297p}=5c83>7}:>031>k84=7;;>4>63ty99n4?:3y>2;|q11`<72;q6:5j52g4893>e28297p}=5g83>7}:k84=5d5>4>63ty9:=4?:3y>0cg=:o<019h9:0:1?xu5>80;6?u23b796c0<5:i?6<6>;|q127<72;q6?n852g4896e328297p}=6283>7}:>9:1>k84=4df>4>63ty9:94?:3y>257=:o<018hj:0:1?xu5><0;6?u255396c0<5<>;6<6>;|q123<72;q699<52g48902728297p}=6683>7}:>;81>k84=421>4>43ty9:54?:3y>275=:o<018>=:0:2?xu5>00;6?u23cg96c0<5:ho6<6>;|q12d<72;q6?oh52g4896dc28297p}=6c83>7}:=931>k84=42;>4>63ty9:n4?:3y>15g=:o<018>7:0:1?xu5>m0;6?u251196c0<5<:?6<6>;|q12`<72;q697}:=9o1>k84=42e>4>63ty9;=4?:3y>0c1=:o<019h7:0:2?xu5?80;6?u24d:96c0<5=o26<6=;|q137<72;q69?952g48904>28297p}=7283>7}:=;21>k84=40:>4>63ty9;94?:3y>0ab=:o<019ji:0:1?xu5?<0;6?u24eg96c0<5=nm6<6>;|q133<72;q68hm52g4891cc282:7p}=7683>7}:<=l1>k84=573>4>63ty9;54?:3y>071=:o<019<6:0:1?xu5?00;6?u243:96c0<5=826<6>;|q13d<72;q6:9j52g48932a28297p}=7c83>7}:>=o1>k84=76e>4>63ty9;n4?:3y>211=:o<01;:6:0:1?xu5?l0;6?u265:96c0<5?>26<6>;|q13c<72;q6?;=52g48960228297p}=8183>7}:;?>1>k84=246>4>63ty94<4?:3y>70`=:o<01>8>:0:1?xu50;0;6?u237296c0<5:<:6<6>;|q1<6<72;q6?8l52g48963c28297p}=8583>7}:;k84=27g>4>63ty9484?:3y>21g=:o<01;:l:0:1?xu50?0;6?u265`96c0<5?>h6<6>;|q1<2<72;q6:9?52g48932428297p}=8883>7}:>=81>k84=760>4>63ty94l4?:3y>701=:o<01>;6:0:1?xu50k0;6?u234:96c0<5:?26<6>;|q17}:;<>1>k84=276>4>63ty94h4?:3y>71`=:o<01>;>:0:1?xu50o0;6?u234296c0<5:?:6<6>;|q1=5<72;q6?9l52g48962c28297p}=9083>7}:;=i1>k84=26g>4>63ty95?4?:3y>711=:o<01>:6:0:1?xu51=0;6?u235:96c0<5:>26<6>;|q1=0<72;q69>o52g48905e28297p}=9783>7}:>j<1>k84=7a4>4>63ty95:4?:3y>2f5=:o<01;m;:0:2?xu5110;6?u268796c0<5?3=6<6>;|q1=<<72;q6:4<52g4893?4282:7p}=9`83>7}:<<81>k84=570>4>53ty95o4?:3y>20?=9m?0186m:0:0?xu51j0;6?u262595a3<5?9=6<6=;|q1=a<72;q6:>651e7891db28297p}=9d83>7}:>:l1=i;4=71f>4>53ty95k4?:3y>216=9m?0197::0:0?xu5i90;6?u262`95a3<5?9j6<6=;|q1e4<72;q6:9;51e78932328297p}=a383>7}:4>33ty9m>4?:3y>20d=9m?018l9:0:0?xu5i=0;6?u264:95a3<5<226<6;;|q1e0<72;q69kj51e7890>428287p}=a783>7}:;><1=i;4=5c;>4>33ty9m:4?:3y>2a?=9m?01;l6:0:0?x{imhk1<7?tH23;?xhbik0;68:madc=83;pD>?7;|lfec<728qC?<64}oga4?6=9rB8=55rnd`2>5<6sA9:46saec094?7|@:;37p`jb283>4}O;820qckm4;295~N4911vbhl::182M5602weio850;3xL67?3tdnn:4?:0yK74>51zJ05==zflh26=4>{I12<>{imkk1<7?tH23;?xhbjk0;68:magc=83;pD>?7;|lffc<728qC?<64}og`4?6=9rB8=55rnda2>5<6sA9:46saeb094?7|@:;37p`jc283>4}O;820qckl4;295~N4911vbhm::182M5602wein850;3xL67?3tdno:4?:0yK74>51zJ05==zfli26=4>{I12<>{imjk1<7?tH23;?xhbkk0;68:mafc=83;pD>?7;|lfgc<728qC?<64}ogg4?6=9rB8=55rndf2>5<6sA9:46saee094?7|@:;37p`jd283>4}O;820qckk4;295~N4911vbhj::182M5602weii850;3xL67?3tdnh:4?:0yK74>51zJ05==zfln26=4>{I12<>{immk1<7?tH23;?xhblk0;68:maac=83;pD>?7;|lf`c<728qC?<64}ogf4?6=9rB8=55rndg2>5<6sA9:46saed094?7|@:;37p`je283>4}O;820qckj4;295~N4911vbhk::182M5602weih850;3xL67?3tdni:4?:0yK74>51zJ05==zflo26=4>{I12<>{imlk1<7?tH23;?xhbmk0;68:ma`c=83;pD>?7;|lfac<728qC?<64}oge4?6=9rB8=55rndd2>5<6sA9:46saeg094?7|@:;37p`jf283>4}O;820qcki4;295~N4911vbhh::182M5602weik850;3xL67?3tdnj:4?:0yK74>51zJ05==zfll26=4>{I12<>{imok1<7?tH23;?xhbnk0;68:macc=83;pD>?7;|lfbc<728qC?<64}od34?6=9rB8=55rng22>5<6sA9:46saf1094?7|@:;37p`i0283>4}O;820qch?4;295~N4911vbk>::182M5602wej=850;3xL67?3tdm<:4?:0yK74>51zJ05==zfo:26=4>{I12<>{in9k1<7?tH23;?xha8k0;68:mb5c=83;pD>?7;|le4c<728qC?<64}od24?6=9rB8=55rng32>5<6sA9:46saf0094?7|@:;37p`i1283>4}O;820qch>4;295~N4911vbk?::182M5602wej<850;3xL67?3tdm=:4?:0yK74>51zJ05==zfo;26=4>{I12<>{in8k1<7?tH23;?xha9k0;68:mb4c=83;pD>?7;|le5c<728qC?<64}od14?6=9rB8=55rng02>5<6sA9:46saf3094?7|@:;37p`i2283>4}O;820qch=4;295~N4911vbk<::182M5602wej?850;3xL67?3tdm>:4?:0yK74>51zJ05==zfo826=4>{I12<>{in;k1<7?tH23;?xha:k0;68:mb7c=83;pD>?7;|le6c<728qC?<64}od04?6=9rB8=55rng12>5<6sA9:46saf2094?7|@:;37p`i3283>4}O;820qch<4;295~N4911vbk=::182M5602wej>850;3xL67?3tdm?:4?:0yK74>51zJ05==zfo926=4>{I12<>{in:k1<7?tH23;?xha;k0;68:mb6c=83;pD>?7;|le7c<728qC?<64}od74?6=9rB8=55rng62>5<6sA9:46saf5094?7|@:;37p`i4283>4}O;820qch;4;295~N4911vbk:::182M5602wej9850;3xL67?3tdm8:4?:0yK74>51zJ05==zfo>26=4>{I12<>{in=k1<7?tH23;?xha8:mb1c=83;pD>?7;|le0c<728qC?<64}od64?6=9rB8=55rng72>5<6sA9:46saf4094?7|@:;37p`i5283>4}O;820qch:4;295~N4911vbk;::182M5602wej8850;3xL67?3tdm9:4?:0yK74>47>51zJ05==zfo?26=4>{I12<>{in8:mb0c=83;pD>?7;|le1c<728qC?<64}od54?6=9rB8=55rng42>5<6sA9:46saf7094?7|@:;37p`i6283>4}O;820qch94;295~N4911vbk8::182M5602wej;850;3xL67?3tdm::4?:0yK74>51zJ05==zfo<26=4>{I12<>{in?k1<7?tH23;?xha>k0;68:mb3c=83;pD>?7;|le2c<728qC?<64}od44?6=9rB8=55rng52>5<6sA9:46saf6094?7|@:;37p`i7283>4}O;820qch84;295~N4911vbk9::182M5602wej:850;3xL67?3tdm;:4?:0yK74>51zJ05==zfo=26=4>{I12<>{in>k1<7?tH23;?xha?k0;68:mb2c=83;pD>?7;|le3c<728qC?<64}od;4?6=9rB8=55rng:2>5<6sA9:46saf9094?7|@:;37p`i8283>4}O;820qch74;295~N4911vbk6::182M5602wej5850;3xL67?3tdm4:4?:0yK74>51zJ05==zfo226=4>{I12<>{in1k1<7?tH23;?xha0k0;6c290:wE=>8:mb=c=83;pD>?7;|le5<6sA9:46saf8094?7|@:;37p`i9283>4}O;820qch64;295~N4911vbk7::182M5602wej4850;3xL67?3tdm5:4?:0yK74>51zJ05==zfo326=4>{I12<>{in0k1<7?tH23;?xha1k0;6k3:1=vF<199~jc?c290:wE=>8:mb?7;|le=c<728qC?<64}odb4?6=9rB8=55rngc2>5<6sA9:46saf`094?7|@:;37p`ia283>4}O;820qchn4;295~N4911vbko::182M5602wejl850;3xL67?3tdmm:4?:0yK74>51zJ05==zfok26=4>{I12<>{inhk1<7?tH23;?xhaik0;68:mbdc=83;pD>?7;|leec<728qC?<64}oda4?6=9rB8=55rng`2>5<6sA9:46safc094?7|@:;37p`ib283>4}O;820qchm4;295~N4911vbkl::182M5602wejo850;3xL67?3tdmn:4?:0yK74>51zJ05==zfoh26=4>{I12<>{inkk1<7?tH23;?xhajk0;68:mbgc=83;pD>?7;|lefc<728qC?<64}od`4?6=9rB8=55rnga2>5<6sA9:46safb094?7|@:;37p`ic283>4}O;820qchl4;295~N4911vbkm::182M5602wejn850;3xL67?3tdmo:4?:0yK74>51zJ05==zfoi26=4>{I12<>{injk1<7?tH23;?xhakk0;68:mbfc=83;pD>?7;|legc<728qC?<64}odg4?6=9rB8=55rngf2>5<6sA9:46safe094?7|@:;37p`id283>4}O;820qchk4;295~N4911vbkj::182M5602weji850;3xL67?3tdmh:4?:0yK74>51zJ05==zfon26=4>{I12<>{inmk1<7?tH23;?xhalk0;68:mbac=83;pD>?7;|le`c<728qC?<64}odf4?6=9rB8=55rngg2>5<6sA9:46safd094?7|@:;37p`ie283>4}O;820qchj4;295~N4911vbkk::182M5602wejh850;3xL67?3tdmi:4?:0yK74>51zJ05==zfoo26=4>{I12<>{inlk1<7?tH23;?xhamk0;68:mb`c=83;pD>?7;|leac<728qC?<64}ode4?6=9rB8=55rngd2>5<6sA9:46safg094?7|@:;37p`if283>4}O;820qchi4;295~N4911vbkh::182M5602wejk850;3xL67?3tdmj:4?:0yK74>51zJ05==zfol26=4>{I12<>{inok1<7?tH23;?xhank0;68:mbcc=83;pD>?7;|lebc<728qC?<64}o3345<728qC?<64}o3344<728qC?<64}o3347<728qC?<64}o3346<728qC?<64}o3341<728qC?<64}o3340<728qC?<64}o3343<728qC?<64}o3342<728qC?<64}o334=<728qC?<64}o334<<728qC?<64}o334d<728qC?<64}o334g<728qC?<64}o334f<728qC?<64}o334a<728qC?<64}o334`<728qC?<64}o334c<728qC?<64}o3355<728qC?<64}o3354<728qC?<64}o3357<728qC?<64}o3356<728qC?<64}o3351<728qC?<64}o3350<728qC?<64}o3353<728qC?<64}o3352<728qC?<64}o335=<728qC?<64}o335<<728qC?<64}o335d<728qC?<64}o335g<728qC?<64}o335f<728qC?<64}o335a<728qC?<64}o335`<728qC?<64}o335c<728qC?<64}o3365<728qC?<64}o3364<728qC?<64}o3367<728qC?<64}o3366<728qC?<64}o3361<728qC?<64}o3360<728qC?<64}o3363<728qC?<64}o3362<728qC?<64}o336=<728qC?<64}o336<<728qC?<64}o336d<728qC?<64}o336g<728qC?<64}o336f<728qC?<64}o336a<728qC?<64}o336`<728qC?<64}o336c<728qC?<64}o3375<728qC?<64}o3374<728qC?<64}o3377<728qC?<64}o3376<728qC?<64}o3371<728qC?<64}o3370<728qC?<64}o3373<728qC?<64}o3372<728qC?<64}o337=<728qC?<64}o337<<728qC?<64}o337d<728qC?<64}o337g<728qC?<64}o337f<728qC?<64}o337a<728qC?<64}o337`<728qC?<64}o337c<728qC?<64}o3305<728qC?<64}o3304<728qC?<64}o3307<728qC?<64}o3306<728qC?<64}o3301<728qC?<64}o3300<728qC?<64}o3303<728qC?<64}o3302<728qC?<64}o330=<728qC?<64}o330<<728qC?<64}o330d<728qC?<64}o330g<728qC?<64}o330f<728qC?<64}o330a<728qC?<64}o330`<728qC?<64}o330c<728qC?<64}o3315<728qC?<64}o3314<728qC?<64}o3317<728qC?<64}o3316<728qC?<64}o3311<728qC?<64}o3310<728qC?<64}o3313<728qC?<64}o3312<728qC?<64}o331=<728qC?<64}o331<<728qC?<64}o331d<728qC?<64}o331g<728qC?<64}o331f<728qC?<64}o331a<728qC?<64}o331`<728qC?<64}o331c<728qC?<64}o3325<728qC?<64}o3324<728qC?<64}o3327<728qC?<64}o3326<728qC?<64}o3321<728qC?<64}o3320<728qC?<64}o3323<728qC?<64}o3322<728qC?<64}o332=<728qC?<64}o332<<728qC?<64}o332d<728qC?<64}o332g<728qC?<64}o332f<728qC?<64}o332a<728qC?<64}o332`<728qC?<64}o332c<728qC?<64}o3335<728qC?<64}o3334<728qC?<64}o3337<728qC?<64}o3336<728qC?<64}o3331<728qC?<64}o3330<728qC?<64}o3333<728qC?<64}o3332<728qC?<64}o333=<728qC?<64}o333<<728qC?<64}o333d<728qC?<64}o333g<728qC?<64}o333f<728qC?<64}o333a<728qC?<64}o333`<728qC?<64}o333c<728qC?<64}o33<5<728qC?<64}o33<4<728qC?<64}o33<7<728qC?<64}o33<6<728qC?<64}o33<1<728qC?<64}o33<0<728qC?<64}o33<3<728qC?<64}o33<2<728qC?<64}o33<=<728qC?<64}o33<<<728qC?<64}o336;123456789>;7=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<=>?0123456789:;<95?0137?567:=1;<=:;;12331=7892?7=>>059344>339::N95?00D7?565M=1;<9>;;12731=78<9?7=>90593422339:3<95?0907?56FK=1;3K=1;M=7;;1C3G1=7J92?7=M?4593G4B339N;J95?F137?5@7:=1;J=8;;1D3<1=7N8L:7<<411685567<2;;4=:4103A0>7489>0=>KL2:370>73=980=8?;;079MKVR\3KOH_O31583:42<9<0BB][[:@FGVG:6<3:586?:FG08532<9?:;>6?84:3;454<9K;0>?5=059145633;:=;347?717N=19;?O=;3:7?7>11890>7AZTQWW>ace}n6:6=0=;3C7?7B00=19I>H;;3G5G1=5MHK97?H;;22147=49=18=>>;;20241=4::=:86==:HLSQQ?50?31?64=AGZ^X7JFA=12>586:2996D@_UU8GMG:493:5=;5<2;MVPUSS2HNO^RA33083:43<;;0DYY^ZT;FBPZI;;80;2<=4338LQQVR\3NDM1=>:1<27>552F__\XZ5DN@?74<76=18?><=;257?6D0N81?>6:?4:63452<<9I;86:?E@08042<<=?;>6::4:66052<<AOWJ591<3??;58JJUSS2^OJ0>4?>0280?OIX\^1[HL33;2=57=32F__\XZ5DNRB86<7688087AZTQWW>AIWJ591<3?<;58LQQVR\3YN@RA33;2=0>2D89>08NML4:6@AF4<08H:;4:6E012<=9>?86;>41681163<2??==:455DF0>32::>098;<4:762D2<=?3J86;807681<0F:2?O86;K09681C2D920F<20FIH80:N:46BA@0>0A8O;0;?58259465653>997:;;;6@EB1=0L;2?7:JME394B1=0N:9?7:HI7594BC@631804=:481230>>7L<804?:483620>>5K:8049:485020>>?09>045H72::B0>>F89>04L>=2::G0>>C89>04H6N4::E<57<1=12<=>;;823=7=>;;12495698:7?>;;8@:<7=>K=12O47=;@21?D753H8?7L<7059B6DG53H9?7L;NC59B1G233H<29?5N859B<7633H23495N8@27?D>F1=1J4KJ;;@C361=FI:I?7LON259BED>33HKJ5?5NB59BF5733HHJ4?5NC49BGNYN:2KO46OKDSC?4;?89B@ATF48;556OKDSC?578>3HNO^L2>3?`8EABUI5;?6=06;@FGVD:6<720MIJ]A=3=<>GCL[K7>364AEFQE95902KOH_O34?:8EABUI5?546OKDSC?2;>GCL[H7<374AEFQF977601JHI\M<03==>GCL[H7=?06;@FGVG:6;7h0MIJ]B=37>58>3HNO^O2>4?:8EABUJ5;546OKDS@?6;>GCL[H7:364AEFQF91902KOH_L38?:8EABUJ53556OKDS]L858f3HNO^RA31114;g3o4AEFQ[J:5;7k0MIJ]_N>10;g1<;g58f3HNO^RA330<:?DBCZVE7?374AEFQ[J:3601JHI\PO=7==>GCL[UD0;06;@FGVZI;?730MIJ]_N>;:<=FLMXTC1714:CF4F2F92H97O?;;C3341=E;89?7O=7059A7D633K>J995M4G21?G>33K28439AB==E]ZUBBKA>;B68G527<2I?89:4C5:30>E3K9>0O8M?4:A5GF40O5>?4:A;4=2;>6M64:A:2640OAEN4:AOOG35LLS;8GJKJA]^NH:5LRDCWAA30H5;?4:F;<=2F02NJXRG30?;8@DRXA5;;245KAU]J847912NJXRG313<:?AGSW@6:?374D@V\M973601OMYQF<07==>BF\VC7=;06;ECW[L:6?730HLZPI=3;:<=CI]UB0<718:FBPZO;9730HLZPI=03:<=CI]UB0??19:FBPZO;:;427IO[_H>17;?89GEQYN4;?556JNT^K?638>3MK_SD2=7?;8@DRXA583245KAU]J87?902NJXRG32?;8@DRXA59;2o5KAU]J867=8730HLZPI=12:==CI]UB0>07;ECW[L:3611OMYQF<4<;?AGSW@6=255KAU]J828?3MK_SD27>99GEQYN40437IO[_N>3:<=CI]UD0<>19:FBPZI;98427IO[_N>26;?89GEQYH48>556JNT^M?508>3MK_SB2>6?;8@DRXG5;<245KAU]L84>912NJXRA318<;?AGSWF6:245KAU]L876912NJXRA320<:?AGSWF69>374D@V\K944601OMYQ@<36==>BF\VE7>806;ECW[J:5>730HLZPO=04:<=CI]UD0?619:FBPZI;:0437IO[_N>1:<=CI]UD0>>1b:FBPZI;;80;245KAU]L867902NJXRA33?:8@DRXG5>546JNT^M?1;>BF\VE753<4DB68@FCD<2NO4I:4DG210>BA0H>0HKHI2:FJ2>BNI5:5;6JFA=33:2=CAH6:=394DHC?57803MCJ0<=17:FJE9736>1OEL2>5?58@LG;9?4<7IGN<05=3>BNI5;32:5KI@>2=;01OEL2=3?58@LG;:=4<7IGN<37=3>BNI58=2:5KI@>13;1508;EKB87?9>2NBM1<17:FJE957601OEL2<1;2=3>BNI59:2;5KI@>0:3=CAH6?2;5KI@>6:3=CAH6=2;5KI@>4:3=CAH632;5KI@>::3=CAK6;2:5KIC>24;169GMG:6<7=0HDL314<4?AOE48<5;6JFB=34:2=CAK6:4394DH@?5<813MCI0<08;EKA8769?2NBN1<>>69GMG:5:7=0HDL322<4?AOE4;>5;6JFB=06:2=CAK69:394DH@?62803MCI0?617:FJF94>6?1OEO2=>69GMG:48730HDL33083:2=CAK68=384DH@?7;089GMUG;;3:5;6JFP@>0:2=CAYH7<394DHRA84803MC[N1<19:FJTG:4294<7IG_B=1=2>BHI5:5;6J@A=33:2=CGH6:=394DNC?57803MEJ0<=17:FLE9736>1OCL2>5?58@JG;9?4<7IAN<05=3>BHI5;32:5KO@>2=;01OCL2=3?58@JG;:=4<7IAN<37=3>BHI58=2:5KO@>13;1508;EMB87?9>2NDM1<17:FLE957601OCL2<1;2=3>BHI59:2;5KO@>0:3=CGH6?2;5KO@>6:3=CGH6=2;5KO@>4:3=CGH632;5KO@>::2=CGHUYIJ84DN@?4;169GKG:6;7=0HBL315<4?AIE48?5;6J@B=35:2=CGK6:;394DN@?5=803MEI0<716:FLF979?2NDN169GKG:597=0HBL323<4?AIE4;95;6J@B=07:2=CGK699394DN@?63803MEI0?917:FLF94?6>1OCO2=9?48@JD;:7=0HBL331<:?AIE4:;1<394DN@?74813MEI0>09;EMA81813MEI0809;EMA83813MEI0:09;EMA8=813MEI0408;EMA[WC@?2ND\L2?>69GKUG;97=0HB^N<3<:?AIWI591<394DNRB86803ME[N1>17:FLTG:66>1OC]L32?;8@JVE4:0;2:5KOQ@?7;57I^]A178@UTF9<1O\_O=5:FSVD563L>0I=>?2:G20>C5IH80I9:4E5670>C2<<80I5:4E9;E0>C?I180IL:4E@A30>CFKH>0IO:>2:G@0>CD89>0INCII:1NBO:4F1030>@7M980J<<4F368B745<2L9J=:4F2G10>@4N;>0J89:4:D6A12=M>6H74:D;<=26H64:D:BA2@FN;?0JLB\E59EF1633OH3O95IBDC7?CDA1=1MOKO=;GF0?CBD<2LOOH=4FEG7?CBAK:1MH]=4FEP7?CBUM=1MH_]:;GFQW@5?7KKNE59EAGG33OOHO95IEGA7?C@79=1MJ=<;;GD3<1=AN;2?7KH=A59EB6433OL?=95IF577?C@3?=1MJ:;;;GD4@1=AN>L?7KH7059EBDE33OLJI95IFE77?C@C0=1MJIH;;GDF41=ANLL?7KHI259EBC133OLM495IFG@7?C@AL=1MJKK>;F18CKB63@80E=<4I008M74OIA]ZT<<64IOKWTZ6502CEEY^P02:8MKOSXV:?46GAIUR\40>98:KMMQVX8>30ECG[SUCWA2=NF@^T<=94IOKW[5703@DBXR>=7:KMMQY7;>1BBDZP0558MKOSW9?<7D@FT^253>OIA]U;;:5FNHV\4=11BBDZP1558MKOSW8?<7D@FT^353>OIA]U:;:5FNHV\5=1B69JJLRX9J=0ECG[_0F4?LHN\V;N;6GAIU]2B2=NF@^T>=94IOKW[7703@DBXR<=7:KMMQY5;>1BBDZP2558MKOSW;?<7D@FT^053>OIA]U9;:5FNHV\6=11BBDZP3558MKOSW:?<7D@FT^153>OIA]U8;:5FNHV\7=178;HLJPZ5F?2CEEYQ2:3=NF]692;5FNU>0:3=NF]6?255FNU>6>5813@D_080<;HLU57=NF_OYXRMCK^FLEZTBO880ECXJRU]@HNYCGKUYIJ84K/1:[I401321>H6898>7C??0278J467<<1E==>:5:L245023G;;<:;4N023<0=I99:296@>0026?K7798?0B<>>249M5574=2D:<<::;O33503H6882>7C??1868J465=2D::;O3364385A11001>H68;>>7C??2478J465><1E==<85:L247>23G;;>4;4N02040=I999:96@>0206?K77;:?0B<><449M5552=2D:<>8:;O33723H68=?0B<>;079M55269<1E==:=5:L241523G;;89;4N02730=I99>296@>0436?K77=:?0B<>:549M5530=2D:<87;;O3320=I99<:96@>0716?K77>9749M550>=2D:<:?:;O33363H68>3?7C??849M55>6=2D:<5=:;O33<03H680;>7C??9278J46>=<1E==784:L25531026?K769;?0B449M5471=2D:=<6;;O3260=I988;96@>1306?K76:=?0B>:;O32773H69:2?7C?>449M5427=2D:=9<:;O32013H69;85A107:0>H69??0B=2D:=:7;;O32<0=I983896@>1876?K761>?0B21;6?K7598?0B<<>549M5770=2D:><7;;O3160=I9;8;96@>2335?K75:8;>7C?=2378J445;<1E=?<;5:L267323G;9>;;4N00130=I9;8396@>23;6?K75;9?0B<<<149M5755=2D:>>=:;O31713H6::=>7C?=3978J4441=1E=?::;O31053996@>2516?K75<=?0B<<;549M5721=2D:>99:;O310=3H6:<;>7C?=5378J442;<1E=?;;5:L260323G;99;;4N00630=I9;?396@>24;7?K75><1E=?8?5:L263723G;9:?;4N00570=I9;2776?K75>??0B<<9749M570?=2D:>;7:;O31353H6:>9>7C?=7578J440=<1E=?995:L262123G;9;5;4N004=1=I9;2>7C?=8178J44?9?1E=?6>149M57>5=2D:>5=:;O31<13H6:1=>7C?=8978J44?1<1E=?7?5:L26<723G;95?;4N00:70=I9;3?96@>2876?K751??0B<<6749M57??=2D:>47<;O300>H6;9?0B<=?049M5666>2D:?=?>5:L275423G;8<>;4N01300=I9::>96@>3146?K748>?0B<=?849M566>=2D:?<>:;O3054385A12301>H6;8>>7C?<1478J456><1E=>?85:L274>23G;8=4:4N0111>H6;;:>7C?<2048J45598?0B<==249M5644=2D:??::;O30603H6;;2>7C?<2878J4548<1E=>=>5:L276423G;8?>;4N01000=I9:9>96@>3246?K74;>?0B<=<849M565><2D:?9;4N01740=I9:>::6@>35321>H6;=8>7C?<4278J453<<1E=>::5:L271023G;88:;4N017<0=I9:>286@>3478J4528<1E=>;>5:L270423G;89>;4N01600=I9:?>96@>3446?K74=>?0B<=:849M563><2D:?;;4N01540=I9:<:96@>3706?K74>:?0B<=9449M5602=2D:?;8:;O30223H6;>:>7C?<7078J450:<1E=>9<5:L272223G;8;8;4N01420=I9:=<96@>36:6?K74?0>0B<=75:L27=623G;84<;4N01;60=I9:2896@>3966?K7400<2D:?4=4N067?K738=1E=9<;;O3700=I9=?:96@>4406?K73=:?0B<::449M5132=2D:888:;O37123>485A157:0>H6=885A15461>H67C?;6678J4210<1E=9864:L2023<<85A15521>H6<>8>7C?;7278J420<<1E=99:5:L202023G;?;:;4N064<0=I9==286@>4978J42?8<1E=96>5:L20=423G;?4>;4N06;00=I9=2>96@>4946?K730>?0B<:7849M51>><2D:84;4N06:40=I9=3:96@>4806?K731:?0B<:6449M51?2=2D:848:;O37=232485A15;:0>H6=9?0B<;?049M5066=2D:9=<:;O36463H6=9<>7C?:0678J4370<1E=8>65:L214623G;>=<84N07254385A14301>H6=8>>7C?:1478J436><1E=8?85:L214>23G;>=4:4N0711>H6=;:>7C?:2078J435:<1E=8<<5:L217223G;>>8;4N07120=I9<8<96@>53:6?K72:0>0B<;<5:L216623G;>?<;4N07060=I9<9896@>5266?K72;6:;O367<25526?K72<8?0B<;;249M5024=2D:99::;O36003H6==2>7C?:4878J4328<1E=8;>5:L210423G;>9>;4N07600=I996@>5446?K72=>?0B<;:849M503><2D:9;;4N07540=I9<<:96@>5706?K72>:?0B<;9449M5002=2D:9;8:;O36223H6=>?0B<;8049M5016=2D:9:<:;O36363H6=><>7C?:7678J4300<1E=8964:L21=3H6=18>7C?:8278J43?<<1E=86:5:L21=023G;>4:;4N07;<0=I9<2296@>5826?K7218?0B<;6249M50?4=2D:94::;O36=03H6=02>7C?:9868J407=2D::=>:;O3544385A17201>H6>9>>7C?90478J407><1E=;>85:L225>23G;=<4:4N0421>H6>8:>7C?91078J406:<1E=;?<5:L224223G;==8;4N04220=I9?;<96@>60:6?K7190>0B<8=5:L227623G;=><;4N04160=I9?8896@>6366?K71:H6>:8>7C?93278J404<<1E=;=:5:L226023G;=?:;4N040<0=I9?9286@>6578J4038<1E=;:>5:L221423G;=8>;4N04700=I9?>>96@>6546?K71<>?0B<8;849M532>=2D::8>:;O35143>85A17701>H6><>>7C?95478J402><1E=;;85:L220>23G;=94:4N0451>H6>?:>7C?96078J401:<1E=;8<5:L223223G;=:8;4N04520=I9?<<96@>67:6?K71>0?0B<88049M5316<2D::5:4N0530>H6?;>0B<9;4:L23328168J4>5<2D:49:4N0:50>H601>0B<7?4:L2=729768J4??:2D986@=0168J765<2D9<9:4N3250>H58190B??;;O0241=I:88?7C<>459M64033G8:495A2327?K45:=1E>?:;;O0121=I:;287C<<4:L17529<;;O0701=I:=H5=1>0B?8?4:L1272=1E>;6;;O0440=I:>::86@=7368J713<2D9;;;4N35551=I:>2?7C<7049M6=66<2D94<:4N3:10>H50=>0B?6:4:L1<32><2D95=:4N2327>H4:=1E??8;;O11<6=I;:>0B>=94:L07=5?7C=;659M71>43G9=86@<6068J60?<2D8;;=4N2:0?K5>:2D??6@;059M05733G>;995A4147?K270=1E8=7<;O621>H398;?7C:>259M04033G>:4>5A4368J147<2D?>?:4N5070>H3:?>0B9<74:L7752?=<:4N5610>H3<=>0B9::4:L7022386@;5168J136<2D?9>:4N5770>H3=?>0B9;84:L71<5=?95A4777?K21>=1E8;6;;O65=1=I<>;?7C:8259M02233G><995A4657?K200:1E85:4N5:00>H30=>0B9694:L7<22H31>>0B9773:L641=I=9:?7C;?259M15233G?;4>5A5068J077<2D>=?:4N4370>H29?>0B8?73:L661=I=;:>7C;=1068J044<2D>>9:4N4050>H2:>>0B8<64:L6752?;:4N41;0>H2;090B8:;;O7751=I==8?7C;;459M11333G??;95A55:7?K328=1E98<;;O7601=I=<287C;94:L6272;8:4N4557>H20=1E95>;;O7;61=I=1>?7C;7659M1=>33G?2<95A5807?K3><=1E94;;;O7:31=I=0287C8?4:L5452H19=>0B;?94:L5525386@95168J335<2D=9>:4N7760>H1=?>0B;;73:L521=I>?:?7C89159M23533G<=895A67:7?K00:=1E::8<;O4;0>H109>0B;674:L5<<295A7067?K16>=1E;<6<;O517>H0<=1E;8<;;O5676=I??>0B:8?4:L4272H0?:>0B:9:4:L4322=3?6@8859M3=633G=3=95A7917?K1?<=1E;58;;O5;<1=I?0:?7C96259M3<233G=2:95A78:7?K1>1:1E4=:4N9200>H?8<>0B5>84:L;4<2H?9?>0B5?84:L;5=2H?::>0B5<;4:L;6024:4N9130>H?;8>0B5==4:L;762H?;090B5:;;O:741=I0=;?7C6;259M<1533G2?895A8577?K>3>=1E499;;O:7<1=I0=3?7C6:059M<0733G2>>95A8417?K>2<=1E48;;;O:621=I0<=?7C6:859M<0?43G2=86@76178J=069=1E4;<;;O:571=I0?>?7C69559M<3033G2=;95A87:7?K>11=1E4:>;;O:451=I0>8?7C68359M<2233G2<995A8647?K>0?=1E4:6;;O:4=6=I01>0B56?5:L;<4733G23>95A8917?K>?<=1E45;;;O:;21=I01=?7C67859M<=?33G22<95A8837?K>>:=1E44=;;O::01=I00??7C66659M<<133G22495A88;1?K?43G3;86@60168J<66<2D2H>8=>0B4>:4:L:432;2D2=95A9026?K?698>0B4?=4:L:562H>9090B4<;;O;140=I1;;:86@62368J<44<2D2>9:4N8060>H>:?>0B4<84:L:6=2H>;=>0B4=:4:L:732;2D2895A9526?K?398>0B4:=4:L:062?86@64468J<21<2D28::4N86;0>H><0>0B4;?4:L:142>?7C78559M=2033G3<;95A96:7?K?01:1E55:4N8:31>H>08;?7C77259M==533G33895A9977?K??>=1E559;;O;;<1=I113?7C76059M=<733G32>95A9817?K?><=1E54;;;O;:21=I10=?7C76859M=TBIMU\EIZG_C48V@ADMH<0^HILEC78VVRXA01Y_YQF_hlu55=U[]UBSd`y1^KMRZ6>3[oxyaz30?c8V`urd}6;23:6g0?c8V`urd}6:=3o4Rdqvhq:6:7k0^h}zlu>27;g4?c8V`urd}6:93o4Rdqvhq:6>730^h}zlu>2:d=Umzgx1?11`9Qavsk|5;5>l5]erwop979;01Yi~{ct=0=e>Tb{|f0?0>a:Pfwpjs4;49m6\jstnw878412Xnxb{<27:4?`9Qavsk|5?5=45]erwop909i2Xnxb{<7<2=>Tb{|f0:0n;Sgpqir;?7;27_k|umv?<;g0;8V`urd}622<5\8:QBR@BF\H20_HBPO=2=<>UBDVE7=364SDN\K949i2YN@RA33;2=<>UBDVE7?384SNWQG@5<[YE=7^\KY^K4?VTQIEUJ;6]]V@N\F1=T[[K?7^]]B49PPGYH<2^R\Hm4URGQ[SOTAKFN?6XLC89UM@QX\PZN86YLLJ08S@0<_LK7<384WDC?5;0<_LK7>364WDC?7?69>2]NM1=16:UFF969>2]NN1?16:UFF94902]NN1=50?48S@D;;7>0[HQ@b:UQMQCXN@XXXn5XRHVF[HICMVKh7Z\FTD]NKACXJm1\^DZJ_VKGPMYFl2]YEYKPWHFWLZD6l2RB@D@W-YFA$5(6(Z^^N->!1!CPGLO23QEYOT84XRVOMG12RonRGk119[`hYJiceyZh||inl24>^ceVGbbb|Yesqjkk53:d=cmkl0<4?>99gags`484j7icjm^`f858f3mgnaRlj<024;ebjmdUoec2>2?a8`hcjWmce0<=1c:fnahYcag6:83m4dlgn[aoi48<5o6jbel]gmk:6?7i0h`kb_ekm84>9k2nfi`Qkio>2=;db9gi`kXl`d7><0l;eofiZbnf5892n5kmdo\`lh;:=4h7icjm^fjj9426j1oahcPdhl?638d3mgnaRjfn=04:f=celgThd`329<`?akbeVnbb1<6>c9gi`kXl`d7>3m4dlgn[aoi4::5n6jbel]gmk:46k1oahcPdhl?0;d25;bbjmdUocxz3155?f8`hcjWme~x1?9>e9gi`kXlf0<91d:fnahYcg|~7=50k;eofiZbh}}6:53m4dlgn[air|5;5h6jbel]gkpr;:94o7icjm^flqq:597n0h`kb_emvp9456m1oahcPdnww8759l2nfi`Qkotv?618c3mgnaRj`uu>11;bbjmdUocxz329bjmdUocxz38?a8`hcjWme~x171c:knahYflmx7<3j4ilgn[dbcz5;;2i5fmdo\eabu48;5h6gbel]b`at;9;4o7dcjm^cg`w:6;7n0e`kb_`fgv9736m1bahcPaefq8439l2cfi`Qndep?538c3`gnaRokds>23;bojmdUjhi|31?f8mhcjWhno~1e9ji`kXimny0??1d:knahYflmx7>?0k;hofiZgcl{69?3j4ilgn[dbcz58?2i5fmdo\eabu4;?5h6gbel]b`at;:?4o7dcjm^cg`w:5?7n0e`kb_`fgv94?6m1bahcPaefq87?9k2cfi`Qndep?6;bojmdUjhi|33?a8mhcjWhno~1:1c:knahYflmx793m4ilgn[dbcz5<5o6gbel]b`at;?7i0e`kb_`fgv9>9k2cfi`Qndep?=;db9ji`kXl`d7=<0l;hofiZbnf5;92n5fmdo\`lh;9:4h7dcjm^fjj9736j1bahcPdhl?508d3`gnaRjfn=35:f=nelgThd`316<`?lkbeVnbb1?7>b9ji`kXl`d7=40m;hofiZbnf5;5o6gbel]gmk:587i0e`kb_ekm8779k2cfi`Qkio>16;eojmdUoec2=4?a8mhcjWmce0?;1c:knahYcag69:3m4ilgn[aoi4;=5o6gbel]gmk:507i0e`kb_ekm87?9j2cfi`Qkio>1:f=nelgThd`331<`?lkbeVnbb1=>>c9ji`kXl`d7?3l4ilgn[aoi4=4i7dcjm^fjj939j2cfi`Qkio>5:g=nelgThd`37?`8mhcjWmce050m;hofiZbnf535;6gbel]fj4g11c9jjvrXj|c$MIJ]_N]gi`kXzm6:=3?m;hlppZdra&KOH_Q@_eofiZtc4885=o5fnrv\fpo(IMNYSBQkmdo\va:6;7;i7d`|t^`vm*GCL[UDSicjm^pg84299k1bb~zPbtk,EABUWFUoahcPre>21;7e3`dxxRlzi.CG@WYHWmgnaR|k<04=5g=nfz~Tnxg AEFQ[JYcelgT~i2>7?3a?lht|Vh~e"OKDS]L[akbeVxo0<611c9jjvrXj|c$MIJ]_N]gi`kXzm6:53?n;hlppZdra&KOH_Q@_eofiZtc484:n6gasu]aql)FLMXTCRjbel]q`94768h0ec}{_cwj+DBCZVETh`kb_sf?6486j2ceyQmuh-B@ATXGVnfi`Q}d=01:4doi{}Uiyd!NDEP\KZbjmdUyh1<;>0`8mkusWkb#LJKR^M\`hcjW{n7>80>b:kmwqYe}`%JHI\PO^fnahYul58=24:n6gasu]aql)FLMXTCRjbel]q`94?68h0ec}{_cwj+DBCZVETh`kb_sf?6<86i2ceyQmuh-B@ATXGVnfi`Q}d=0=5g=nfz~Tnxg AEFQ[JYcelgT~i2<0?3a?lht|Vh~e"OKDS]L[akbeVxo0>?11`9jjvrXj|c$MIJ]_N]gi`kXzm6820c8mkusWkb#LJKR^M\`hcjW{n743?n;hlppZdra&KOH_Q@_eofiZtc404:56gasu]aql)FLMXTCRjbel]q`Z6612ceyQmuh-B@ATXGVnfi`Q}d^32e>oi{}Uiyd!NDEP\KZbjmdUyhR??1`9jjvrXj|c$MIJ]_N]gi`kXzmU:=50c8mkusWkb#LJKR^M\`hcjW{nT=;?n;hlppZdra&KOH_Q@_eofiZtcW8=:m6gasu]aql)FLMXTCRjbel]q`Z7?9h1bb~zPbtk,EABUWFUoahcPre]2=4?=?n;hlppZdra&KOH_Q@_eofiZtcW;;:m6gasu]aql)FLMXTCRjbel]q`Z459h1bb~zPbtk,EABUWFUoahcPre]174ga:kmwqYe}`%JHI\PO^fnahYulV8==l5fnrv\fpo(IMNYSBQkmdo\vaY5?8k0ec}{_cwj+DBCZVETh`kb_sf\6=7f3`dxxRlzi.CG@WYHWmgnaR|k_3;2=>oi{}Uiyd!NDEP\KZbjmdUyhR=>a:kmwqYe}`%JHI\PO^fnahYulV9;=l5fnrv\fpo(IMNYSBQkmdo\vaY49830ec}{_cwj+DBCZVETh`kb_sf\04?oi{}Uiyd!LYB]L[akbeVxoS`{w01235`=nfz~Tnxg CXA\KZbjmdUyhR``t12354`oi{}Uiyd!LYB]L[akbeVxoSca{01225ZUP88l0ec}{_cwj+F_DWFUoahcPre]mkq67888:96gasu]aql)DQJUDSdmncig2=>oi{}Uiyd!KAU]J[akbeVxo0=0>a:kmwqYe}`%OMYQF_eofiZtc48:5=l5fnrv\fpo(LH^TERjbel]q`97668k0ec}{_cwj+AGSW@UoahcPre>26;7f3`dxxRlzi.FBPZOXldofSj312<2e>oi{}Uiyd!KAU]J[akbeVxo0<:11`9jjvrXj|c$HLZPI^fnahYul5;>27;j7d`|t^`vm*BF\VCTh`kb_sf?5286i2ceyQmuh-GEQYNWmgnaR|k<0:=5d=nfz~Tnxg D@V\MZbjmdUyh1?6>0;8mkusWkb#IO[_H]gi`kXzm6:20c8mkusWkb#IO[_H]gi`kXzm6983?n;hlppZdra&NJXRGPdlgn[wb;:<4:m6gasu]aql)CI]UBSicjm^pg87099h1bb~zPbtk,@DRXAVnfi`Q}d=04:4g40>9:kmwqYe}`%OMYQF_eofiZtc4;4:m6gasu]aql)CI]UBSicjm^pg86699h1bb~zPbtk,@DRXAVnfi`Q}d=12:4?0;8mkusWkb#IO[_H]gi`kXzm6?2<74ioqw[gsn'MK_SDQkmdo\va:26830ec}{_cwj+AGSW@UoahcPre>5:4?0;8mkusWkb#IO[_H]gi`kXzm632<74ioqw[gsn'MK_SDQkmdo\va:>6820ec}{_cwj+AGSW@UoahcPre]35==nfz~Tnxg D@V\MZbjmdUyhR?>9:kmwqYe}`%OMYQF_eofiZtcW8::56gasu]aql)CI]UBSicjm^pg[47612ceyQmuh-GEQYNWmgnaR|k_002=>oi{}Uiyd!KAU]J[akbeVxoS<=>9:kmwqYe}`%OMYQF_eofiZtcW8>:56gasu]aql)CI]UBSicjm^pg[43612ceyQmuh-GEQYNWmgnaR|k_042=>oi{}Uiyd!KAU]J[akbeVxoS<9>9:kmwqYe}`%OMYQF_eofiZtcW82:56gasu]aql)CI]UBSicjm^pg[4?602ceyQmuh-GEQYNWmgnaR|k_33:?lht|Vh~e"JNT^K\`hcjW{nT>=?6;hlppZdra&NJXRGPdlgn[wbX:8;27d`|t^`vm*BF\VCTh`kb_sf\677>3`dxxRlzi.FBPZOXldofSjP223:?lht|Vh~e"JNT^K\`hcjW{nT>9?6;hlppZdra&NJXRGPdlgn[wbX:<;27d`|t^`vm*BF\VCTh`kb_sf\637>3`dxxRlzi.FBPZOXldofSjP263:?lht|Vh~e"JNT^K\`hcjW{nT>5?6;hlppZdra&NJXRGPdlgn[wbX:0;37d`|t^`vm*BF\VCTh`kb_sf\74?oi{}Uiyd!KAU]J[akbeVxoS;?7;hlppZdra&NJXRGPdlgn[wbX?820ec}{_cwj+AGSW@UoahcPre];5==nfz~Tnxg D@V\MZbjmdUyhR7>e:kmwqYe}`%OMYQF_eofiZtcWhdo<=>?1g9jjvrXj|c$HLZPI^fnahYulVkeh=>?0006?lht|Vh~e"Clotlw[gstW}cfib{{_blw[f;87837d`|t^`vm*Kdg|dSo{|_uknajssWjdSnw30?]qp702ceyQmuh-Ngjsi|Vh~RzfmdmvpZei|Vir0<<1279jjvrXj|c$Anaznu]aqvYsadodyyQlnu]`}9746;<0ec}{_cwj+Heh}g~Tnx}PthofkprXkg~Tot2>4?05?lht|Vh~e"Clotlw[gstW}cfib{{_blw[f;9<4996gasu]aql)JkfexRlzs^vji`ir|ViexRmv<0<11>oi{}Uiyd!BcnwmpZdr{V~bahazt^ampZe~4;4996gasu]aql)JkfexRlzs^vji`ir|ViexRmv<2<11>oi{}Uiyd!BcnwmpZdr{V~bahazt^ampZe~4=4996gasu]aql)JkfexRlzs^vji`ir|ViexRmv<4<11>oi{}Uiyd!BcnwmpZdr{V~bahazt^ampZe~4?4996gasu]aql)JkfexRlzs^vji`ir|ViexRmv<6<11>oi{}Uiyd!BcnwmpZdr{V~bahazt^ampZe~414996gasu]aql)JkfexRlzs^vji`ir|ViexRmv<8<13>oi{}Uiyd!BcnwmpZdr{V~bahazt^ampZjr|5;;2?j4ioqw[gsn'DidyczPbtq\plkbg|~ToczPltv?558XAG\T>^KMRZ65?2ceyQmuh-Ngjsi|Vh~RzfmdmvpZei|Vf~x1?=>3f8mkusWkb#@m`uov\fpuX|`gncxzPcov\hpr;9;4TECXP0358mkusWkb#@m`uov\fpuX|`gncxzPcov\hpr;9:49h6gasu]aql)JkfexRlzs^vji`ir|ViexRbzt=30:ZOI^V:9;6gasu]aql)JkfexRlzs^vji`ir|ViexRbzt=37:7b=7:kmwqYe}`%Fob{at^`vwZrnele~xRmat^nvp9716;n0ec}{_cwj+Heh}g~Tnx}PthofkprXkg~T`xz317<\MKPX8;<0ec}{_cwj+Heh}g~Tnx}PthofkprXkg~T`xz31?0`?lht|Vh~e"Clotlw[gstW}cfib{{_blw[iss484TECXP0348mkusWkb#@m`uov\fpuX|`gncxzPcov\hpr;:78h7d`|t^`vm*Kdg|dSo{|_uknajssWjdSa{{<3<\MKPX8;<0ec}{_cwj+Heh}g~Tnx}PthofkprXkg~T`xz33?0`?lht|Vh~e"Clotlw[gstW}cfib{{_blw[iss4:4TECXP0348mkusWkb#@m`uov\fpuX|`gncxzPcov\hpr;<78h7d`|t^`vm*Kdg|dSo{|_uknajssWjdSa{{<5<\MKPX8;<0ec}{_cwj+Heh}g~Tnx}PthofkprXkg~T`xz35?0`?lht|Vh~e"Clotlw[gstW}cfib{{_blw[iss4<4TECXP0348mkusWkb#@m`uov\fpuX|`gncxzPcov\hpr;>78h7d`|t^`vm*Kdg|dSo{|_uknajssWjdSa{{<7<\MKPX8;<0ec}{_cwj+Heh}g~Tnx}PthofkprXkg~T`xz37?0`?lht|Vh~e"Clotlw[gstW}cfib{{_blw[iss4>4TECXP0348mkusWkb#@m`uov\fpuX|`gncxzPcov\hpr;078h7d`|t^`vm*Kdg|dSo{|_uknajssWjdSa{{<9<\MKPX8;<0ec}{_cwj+Heh}g~Tnx}PthofkprXkg~T`xz39?0`?lht|Vh~e"Clotlw[gstW}cfib{{_blw[iss404TECXP0348mkusWkb#@m`uov\fpuX|`gncxzPcov\|jt;878<7d`|t^`vm*Kdg|dSo{|_uknajssWjdSua}<02=62=nfz~Tnxg MbmvjqYe}zUe`k`uu]`jqYg{6:=3<8;hlppZdra&Ghcx`{_cwp[qojmfSn`{_ymq8449:>1bb~zPbtk,Ifirf}Uiy~Q{ilglqqYdf}Usc2>3?04?lht|Vh~e"Clotlw[gstW}cfib{{_blw[}iu48>5>:5fnrv\fpo(Eje~byQmur]wmhch}}UhbyQwos>21;403`dxxRlzi.O`kphsWkxSygbenww[fhsWqey0<81279jjvrXj|c$Anaznu]aqvYsadodyyQlnu]{kw:66;<0ec}{_cwj+Heh}g~Tnx}PthofkprXkg~Ttb|32?05?lht|Vh~e"Clotlw[gstW}cfib{{_blw[}iu4:49:6gasu]aql)JkfexRlzs^vji`ir|ViexRv`r=6=63=nfz~Tnxg MbmvjqYe}zUe`k`uu]`jqYg{6>2?84ioqw[gsn'DidyczPbtq\plkbg|~ToczPxnp?2;413`dxxRlzi.O`kphsWkxSygbenww[fhsWqey0:0=6:kmwqYe}`%Fob{at^`vwZrnele~xRmat^zlv9>9:?1bb~zPbtk,Ifirf}Uiy~Q{ilglqqYdf}Usc26>048mkusWkb#^\KY^K\`fgd`l;<7d`|t^`vm*UULPUBSimncig253=nfz~Tnxg SSFZ[LYnkhici<94ioqw[gsn'ZXOURGPibc`l`76=2ceyQmuh-PPGYH9VCEZR>>9:kmwqYe}`%icxzPfhdl[aoi494:m6gasu]aql)eg|~Tjdh`_ekm84699h1bb~zPbtk,fjssWocmcRjfn=32:4g2?3b?lht|Vh~e"l`uu]emciXl`d7=>0>a:kmwqYe}`%icxzPfhdl[aoi48>5=l5fnrv\fpo(jfSkgio^fjj97268k0ec}{_cwj+gir|VlbjbQkio>22;7f3`dxxRlzi.`lqqYaaoeThd`316<2e>oi{}Uiyd!motv\bl`hWmce0<611`9jjvrXj|c$nb{{_gkekZbnf5;22<74ioqw[gsn'ke~xRhffn]gmk:668k0ec}{_cwj+gir|VlbjbQkio>14;7f3`dxxRlzi.`lqqYaaoeThd`320<2e>oi{}Uiyd!motv\bl`hWmce0?<11`9jjvrXj|c$nb{{_gkekZbnf58820c8mkusWkb#oazt^djbjYcag6943?n;hlppZdra&hdyyQiigm\`lh;:04:56gasu]aql)eg|~Tjdh`_ekm8786i2ceyQmuh-akprXn`ldSiga<22=5d=nfz~Tnxg bnww[coagVnbb1=>>0c8mkusWkb#oazt^djbjYcag68>3?n;hlppZdra&hdyyQiigm\`lh;;:4:m6gasu]aql)eg|~Tjdh`_ekm86299h1bb~zPbtk,fjssWocmcRjfn=16:4ga:kmwqYe}`%icxzPfhdl[aoi4:25=l5fnrv\fpo(jfSkgio^fjj95>6830ec}{_cwj+gir|VlbjbQkio>0:4ga:kmwqYe}`%icxzPfhdl[aoi4=85=l5fnrv\fpo(jfSkgio^fjj92468k0ec}{_cwj+gir|VlbjbQkio>70;7f3`dxxRlzi.`lqqYaaoeThd`344<2e>oi{}Uiyd!motv\bl`hWmce09811`9jjvrXj|c$nb{{_gkekZbnf5><2oi{}Uiyd!motv\bl`hWmce08>11`9jjvrXj|c$nb{{_gkekZbnf5?:20c8mkusWkb#oazt^djbjYcag6>:3?n;hlppZdra&hdyyQiigm\`lh;=>4:m6gasu]aql)eg|~Tjdh`_ekm80>99h1bb~zPbtk,fjssWocmcRjfn=7::4?0c8mkusWkb#oazt^djbjYcag6=<3?n;hlppZdra&hdyyQiigm\`lh;>84:m6gasu]aql)eg|~Tjdh`_ekm83499h1bb~zPbtk,fjssWocmcRjfn=40:4ga:kmwqYe}`%icxzPfhdl[aoi4?<5=l5fnrv\fpo(jfSkgio^fjj90068k0ec}{_cwj+gir|VlbjbQkio>5<;7>3`dxxRlzi.`lqqYaaoeThd`36?3:?lht|Vh~e"l`uu]emciXl`d7;3?6;hlppZdra&hdyyQiigm\`lh;07;27d`|t^`vm*dh}}UmekaPdhl?=;473`dxxRlzi.`lqqYaaoeThd`P0^ov|5678;;0ec}{_cwj+gir|VlbjbQkio]3[hs89:;=??4ioqw[gsn'ke~xRhffn]gmkY7Wds<=>?2318mkusWkb#oazt^djbjYcagU;S`{w0123[c3592ceyQmuh-akprXn`ldSiga_02\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[46Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU:PF318mkusWkb#oazt^djbjYcagU:=Rczx1234ZA592ceyQmuh-akprXn`ldSiga_00\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[44Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU:>Rczx1234ZA592ceyQmuh-akprXn`ldSiga_01\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[45Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU:?Rczx1234ZA592ceyQmuh-akprXn`ldSiga_06\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[42Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU:8Rczx1234ZA592ceyQmuh-akprXn`ldSiga_07\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[43Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU:9Rczx1234ZA592ceyQmuh-akprXn`ldSiga_04\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[40Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU::Rczx1234ZA592ceyQmuh-akprXn`ldSiga_05\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[41Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU:;Rczx1234ZA592ceyQmuh-akprXn`ldSiga_0:\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[4>Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU:4Rczx1234ZA592ceyQmuh-akprXn`ldSiga_0;\ip~789:9?6gasu]aql)eg|~Tjdh`_ekm[4?Xe|r;<=>PF318mkusWkb#oazt^djbjYcagU:5Rczx1234ZA582ceyQmuh-akprXn`ldSiga_0]nq}67898:7d`|t^`vm*dh}}UmekaPdhl\5Zkrp9:;<<<>;hlppZdra&hdyyQiigm\`lhX9Vg~t=>?0300?lht|Vh~e"l`uu]emciXl`dT=Rczx1234Z`2:81bb~zPbtk,fjssWocmcRjfn^03[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ47Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>=Qbuy2345Y@:81bb~zPbtk,fjssWocmcRjfn^02[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ46Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>>5fnrv\fpo(jfSkgio^fjjZ45Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>?Qbuy2345Y@:81bb~zPbtk,fjssWocmcRjfn^00[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ44Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>>Qbuy2345Y@:81bb~zPbtk,fjssWocmcRjfn^07[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ43Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>9Qbuy2345Y@:81bb~zPbtk,fjssWocmcRjfn^06[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ42Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>8Qbuy2345Y@:81bb~zPbtk,fjssWocmcRjfn^05[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ41Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>;Qbuy2345Y@:81bb~zPbtk,fjssWocmcRjfn^04[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ40Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>:Qbuy2345Y@:81bb~zPbtk,fjssWocmcRjfn^0;[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ4?Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>5Qbuy2345Y@:81bb~zPbtk,fjssWocmcRjfn^0:[hs89:;>>5fnrv\fpo(jfSkgio^fjjZ4>Wds<=>?_G00?lht|Vh~e"l`uu]emciXl`dT>4Qbuy2345Y@:91bb~zPbtk,fjssWocmcRjfn^0\ip~789:9>6gasu]aql)eg|~Tjdh`_ekm[7Yj}q:;<=QI239jjvrXj|c$nb{{_gkekZbnfV8Taxv?012\C77Taxv?012267=nfz~Tnxg bnww[coagVnbbR=:_lw{45679;80ec}{_cwj+gir|VlbjbQkio]02Zkrp9:;<<<=;hlppZdra&hdyyQiigm\`lhX;>Ufyu>?01316>oi{}Uiyd!motv\bl`hWmceS>6Pmtz34566:;1bb~zPbtk,fjssWocmcRjfn^1:[hs89:;=?>4ioqw[gsn'ke~xRhffn]gmkY4Wds<=>?239jjvrXj|c$nb{{_gkekZbnfV9Taxv?012\B74?01316>oi{}Uiyd!motv\bl`hWmceS9;Pmtz34566:;1bb~zPbtk,fjssWocmcRjfn^65[hs89:;=?<4ioqw[gsn'ke~xRhffn]gmkY3?Vg~t=>?0001?lht|Vh~e"l`uu]emciXl`dT85Qbuy234575:2ceyQmuh-akprXn`ldSiga_5;\ip~789::>=5fnrv\fpo(jfSkgio^fjjZ2Xe|r;<=>=2:kmwqYe}`%icxzPfhdl[aoiW=Ufyu>?01]E67=nfz~Tnxg bnww[coagVnbbR:Pmtz3456XO;80ec}{_cwj+gir|VlbjbQkio]64Zkrp9:;<<<=;hlppZdra&hdyyQiigm\`lhX=8Ufyu>?01316>oi{}Uiyd!motv\bl`hWmceS8?0001?lht|Vh~e"l`uu]emciXl`dT98Qbuy234575:2ceyQmuh-akprXn`ldSiga_44\ip~789::>?5fnrv\fpo(jfSkgio^fjjZ30Wds<=>?1308mkusWkb#oazt^djbjYcagU>4Rczx12344453`dxxRlzi.`lqqYaaoeThd`P58]nq}6789;9<6gasu]aql)eg|~Tjdh`_ekm[0Yj}q:;<=<=;hlppZdra&hdyyQiigm\`lhX=Vg~t=>?0^D16>oi{}Uiyd!motv\bl`hWmceS8Qbuy2345Y@:;1bb~zPbtk,fjssWocmcRjfn^43[hs89:;=?<4ioqw[gsn'ke~xRhffn]gmkY19Vg~t=>?0001?lht|Vh~e"l`uu]emciXl`dT:?Qbuy234575:2ceyQmuh-akprXn`ldSiga_71\ip~789::>?5fnrv\fpo(jfSkgio^fjjZ03Wds<=>?1308mkusWkb#oazt^djbjYcagU=9Rczx12344453`dxxRlzi.`lqqYaaoeThd`P67]nq}6789;9>6gasu]aql)eg|~Tjdh`_ekm[31Xe|r;<=>>219jjvrXj|c$nb{{_gkekZbnfVoi{}Uiyd!motv\bl`hWmceS;Qbuy2345YA:;1bb~zPbtk,fjssWocmcRjfn^4\ip~789:TK?>4ioqw[gsn'ke~xRhffn]gmkY0Wds<=>?239jjvrXj|c$nb{{_gkekZbnfV=Taxv?012\B74?_G01?lht|Vh~e"l`uu]emciXl`dT4Rczx1234ZA582ceyQmuh-akprXn`ldSiga_8]nq}6789897d`|t^`vm*dh}}UmekaPdhl\=Zkrp9:;?01]D54=nfz~Tnxg btq\majb9=1bb~zPbtk,fpuX|`gncxz>b:kmwqYe}`%iy~Q{ilglqqYdf}6;222;7e3`dxxRlzi.`vwZrnele~xRmat=3=5g=nfz~Tnxg btq\plkbg|~Tocz32?3a?lht|Vh~e"lzs^vji`ir|Viex1=11c9jjvrXj|c$nx}PthofkprXkg~783?m;hlppZdra&h~RzfmdmvpZei|5?5=o5fnrv\fpo(j|yTxdcjotv\gkr;>7;i7d`|t^`vm*dr{V~bahazt^amp9199k1bb~zPbtk,fpuX|`gncxzPcov?<;7e3`dxxRlzi.`vwZrnele~xRmat=;=5d=nfz~Tnxg btq\plkbg|~ToczP00c8mkusWkb#o{|_uknajssWjdS:91bb~zPbtk,fpuX|`gncxzPcov\ekb789:956gasu]aql)e}zUe`k`uu]`jqYffm:;<=Qxg^az858512ceyQmuh-aqvYsadodyyQlnu]bja6789U|kRmv<0<1=>oi{}Uiyd!mur]wmhch}}UhbyQnne2345YpoVir0?0=9:kmwqYe}`%iy~Q{ilglqqYdf}Ujbi>?01]tcZe~4:4956gasu]aql)e}zUe`k`uu]`jqYffm:;<=Qxg^az8185i2ceyQmuh-aqvYsadodyyQlnu]bja6789U|kRbzt=2=75=nfz~Tnxg btq\plkbg|~ToczPaof3456XnUgyy2?>^KMRZ65i2ceyQmuh-aqvYsadodyyQlnu]bja6789U|kRbzt=3=6d=nfz~Tnxg btq\plkbg|~ToczPaof3456XnUgyy2=>3c8mkusWkb#o{|_uknajssWjdSl`k0123[raXd|~7?3?0^ud[iss4=49<6gasu]aql)e}zUe`k`uu]`jqYig}:;<=<8;hlppZdra&h~RzfmdmvpZei|Vddx=>?00]JJSY7901bb~zPbtk,gusXldofSiga<1<25d=nfz~Tnxg cqw\`hcjWmce0<>110c8mkusWkb#n~z_eofiZbnf5;:203b?lht|Vh~e"mu^fnahYcag6:;3?>a:kmwqYe}`%h|xQkmdo\`lh;914:=l5fnrv\fpo(kyTh`kb_ekm84?99830ec}{_cwj+fvrWmgnaRjfn=3=54g03b?lht|Vh~e"mu^fnahYcag69=3?>a:kmwqYe}`%h|xQkmdo\`lh;:;4:=l5fnrv\fpo(kyTh`kb_ekm872998k0ec}{_cwj+fvrWmgnaRjfn=06:47f3`dxxRlzi.asqZbjmdUoec2=6?32e>oi{}Uiyd!lpt]gi`kXl`d7>:0>1`9jjvrXj|c$o}{Pdlgn[aoi4;25=68;27d`|t^`vm*ew}Vnfi`Qkio>1:47f3`dxxRlzi.asqZbjmdUoec2<0?32=>oi{}Uiyd!lpt]gi`kXl`d7?3?>9:kmwqYe}`%h|xQkmdo\`lh;<7;:56gasu]aql)dx|UoahcPdhl?1;7612ceyQmuh-`tpYcelgThd`36?32=>oi{}Uiyd!lpt]gi`kXl`d743?>9:kmwqYe}`%h|xQkmdo\`lh;17;:96gasu]aql)dx|UoahcPesp2g>oi{}Uiyd!lpt]gi`kXm{xTc>?013g?lht|Vh~e"mu^fnahYbz{Ud~=>?0036?lht|Vh~e"mu^knahYbz{;?7d`|t^`vm*bdijbnSo{|y058mkusWkb#imncig\`jss494:46gasu]aql)ckhiciRj`uu>24;7?3`dxxRlzi.f`efnbWme~x1?>>0:8mkusWkb#imncig\`jss4885=55fnrv\fpo(ljkhdhQkotv?568602ceyQmuh-ggdeomVndyy2>4?3;?lht|Vh~e"jlabjf[air|5;>2<64ioqw[gsn'mijoekPdnww8409911bb~zPbtk,`fgd`lUocxz316<2<>oi{}Uiyd!kc`akaZbh}}6:43?7;hlppZdra&nhmnfj_emvp97>68=0ec}{_cwj+aefkaoThb{{<0<2<>oi{}Uiyd!kc`akaZbh}}69<3?7;hlppZdra&nhmnfj_emvp9466820ec}{_cwj+aefkaoThb{{<30=5==nfz~Tnxg dbc`l`Ycg|~7>>0>8:kmwqYe}`%oolmge^flqq:5<7;37d`|t^`vm*bdijbnSiazt=06:4>4:46gasu]aql)ckhiciRj`uu>1<;7?3`dxxRlzi.f`efnbWme~x1<6>058mkusWkb#imncig\`jss4;4:46gasu]aql)ckhiciRj`uu>04;7?3`dxxRlzi.f`efnbWme~x1=>>058mkusWkb#imncig\`jss4:4:;6gasu]aql)ckhiciRj`uu>7:417:kmwqYe}`%oolmge^flqq:168=0ec}{_cwj+aefkaoThb{{<6<23>oi{}Uiyd!kc`akaZbh}}632<94ioqw[gsn'mijoekPdnww8<86:2ceyQmuh-ggdeomVoe==5fnrv\fpo(ljkhdhj>1:kmwqYe}`%oolmgee32<>oi{}Uiyd!kmdo\i`kXzmUlby?8;hlppZdra&chmnfj_lgn[bhs;81bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-NvdkXZHG:??5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)JzhgT^LC>0208mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$Aob_SCN54553`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/LpbiZTFE888>6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*KuidUYM@?<339jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O2064w0p,IwgjW[KF=4=>;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'DxjaR\NM311?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#@|nm^PBI764:2ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.OqehYUID8:??5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)JzhgT^LC=2208mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$Aob_SCN66553`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/LpbiZTFE;>8>6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*KuidUYM@<:339jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O1264997d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+HtfeVXJA?6<2:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&Gym`Q]AL0:74=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!Br`o\VDK4;;1bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-NvdkXZHG8<><4ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(E{kfS_OB3011?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#@|nm^PBI644:2ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.OqehYUID98??5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)JzhgT^LC<4208mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$Aob_SCN70553`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/LpbiZTFE:<8>6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*KuidUYM@=8339jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O0<64oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"C}al]QEH26;;1bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-NvdkXZHG?>><4ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(E{kfS_OB4211?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#@|nm^PBI124:2ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.OqehYUID>>??5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)JzhgT^LC;6208mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$Aob_SCN02553`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/LpbiZTFE=28>6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*KuidUYM@:6309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O677=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!Br`o\VDK28:80ec}{_cwj+lht|VhdyyQiigm,mkusWmzym`Q>w0p,IwgjW[KF9<==;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'DxjaR\NM4006>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"C}al]QEH34;;1bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-NvdkXZHG>8><4ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(E{kfS_OB5411?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#@|nm^PBI004:2ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.OqehYUID?<2:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&Gym`Q]AL4277=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!Br`o\VDK1::80ec}{_cwj+lht|VhdyyQiigm,mkusWmzym`Q>w0p,IwgjW[KF:>==;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'DxjaR\NM7606>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"C}al]QEH02;;1bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-NvdkXZHG=:><4ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(E{kfS_OB6611?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#@|nm^PBI3>4:2ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.OqehYUID<2?<5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)JzhgT^LC8309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O;74=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!Br`o\VDK>;11bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-\rdtnfmos<=>?<1<0=>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"Qyaskm``~789:7==0<9:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&U}mgaddz3456;984856gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?578412ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.]uewoillr;<=>312<0=>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"Qyaskm``~789:7=90<9:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&U}mgaddz3456;9<4856gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?538412ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.]uewoillr;<=>316<0=>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"Qyaskm``~789:7=50<9:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&U}mgaddz3456;904846gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?5;5>3`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/^tbvlhcmq:;<=2=0?1:?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}678969=3=6;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:5:7927d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+Zpfz`doiu>?01>17;5>3`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/^tbvlhcmq:;<=2=4?1:?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}67896993=6;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:5>7927d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+Zpfz`doiu>?01>13;5>3`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/^tbvlhcmq:;<=2=8?1:?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}67896953=7;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:56:30ec}{_cwj+lht|VhdyyQiigm,mkusWmzym`Q>w0p,[sguagnnt=>?0=13:6?>2;8mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$S{o}ioff|56785992>74ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(Wkyecjjx12349546:30ec}{_cwj+lht|VhdyyQiigm,mkusWmzym`Q>w0p,[sguagnnt=>?0=17:6?2;8mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$S{o}ioff|567859=2>74ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(Wkyecjjx12349506:30ec}{_cwj+lht|VhdyyQiigm,mkusWmzym`Q>w0p,[sguagnnt=>?0=1;:6?2:8mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$S{o}ioff|5678595?45fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)X~hxbbikw01238169;01bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-\rdtnfmos<=>?<53=7<=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!Pv`pjjac89:;09<1389jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%Tzl|fneg{45674=95?45fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)X~hxbbikw01238129;01bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-\rdtnfmos<=>?<57=7<=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!Pv`pjjac89:;0981389jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%Tzl|fneg{45674==5?45fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)X~hxbbikw012381>9;01bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-\rdtnfmos<=>?<5;=7==nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!Pv`pjjac89:;090<9:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&U}mgaddz3456;=94856gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?148412ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.]uewoillr;<=>353<0=>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"Qyaskm``~789:79>0<9:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&U}mgaddz3456;==4856gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?108412ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.]uewoillr;<=>357<0=>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"Qyaskm``~789:79:0<9:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&U}mgaddz3456;=14856gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?1<8402ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.]uewoillr;<=>35?1:?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}67896=<3=6;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:197927d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+Zpfz`doiu>?01>56;5>3`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/^tbvlhcmq:;<=293?1:?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}67896=83=6;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:1=7927d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+Zpfz`doiu>?01>52;5>3`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/^tbvlhcmq:;<=297?1:?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}67896=43=7;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:16:20ec}{_cwj+lht|VhdyyQiigm,mkusWmzym`Q>w0p,[sguagnnt=>?0=5=7==nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!Pv`pjjac89:;050<8:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&U}mgaddz3456;179;7d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+air|VhT<>>4ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(lfSoQ>309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb^3374=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!kotv\fZ76;81bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-gkprXjV;9?<5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)cg|~TnR?<309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb^3774=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!kotv\fZ72;81bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-gkprXjV;=?<5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)cg|~TnR?8309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb^3;74=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!kotv\fZ7>;91bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-gkprXjV88=6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*bh}}UiS?><1:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&ndyyQm_3305>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"j`uu]a[74492ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.flqqYeW;98=6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*bh}}UiS?:<1:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&ndyyQm_3705>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"j`uu]a[70492ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.flqqYeW;=8=6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*bh}}UiS?6<1:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&ndyyQm_3;04>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"j`uu]a[6563`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/emvpZdX;99:7d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+air|VhT?<=>;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'me~xRlP3312?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#iazt^`\76563`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/emvpZdX;=9:7d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+air|VhT?8=>;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'me~xRlP3712?lht|Vh~e"gasu]akprXn`ld#d`|t^fsvdkX9~;y#iazt^`\72563`dxxRlzi.kmwqYeg|~Tjdh`/hlppZbwzhgT=z?}/emvpZdX;19:7d`|t^`vm*oi{}UicxzPfhdl+lht|Vn{~lcP1v3q+air|VhT?4=?;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'me~xRlP4238mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$hb{{_c]7467w0p,`jssWkU?>>?4ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(lfSoQ;3238mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$hb{{_c]7067w0p,`jssWkU?:>?4ioqw[gsn'`dxxRl`uu]emci(agySi~}al]2s4t(lfSoQ;7238mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$hb{{_c]7<67w0p,`jssWkU>?<5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)cg|~TnR;?309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb^7274=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!kotv\fZ35;81bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-gkprXjV?8?<5fnrv\fpo(agySoazt^djbj)nfz~Th}|nm^3t5w)cg|~TnR;;309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb^7674=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!kotv\fZ31;81bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-gkprXjV?r.flqqYeW?:8=6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*bh}}UiS;?<1:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&ndyyQm_7005>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"j`uu]a[35492ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.flqqYeW?>8=6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*bh}}UiS;;<1:kmwqYe}`%bb~zPbnww[coag&ceyQkpscn[4q6z&ndyyQm_7405>oi{}Uiyd!fnrv\fjssWocmc"gasu]gtwgjW8}:~"j`uu]a[31492ceyQmuh-jjvrXjfSkgio.kmwqYcx{kfSr.flqqYeW?28<6gasu]aql)nfz~Tnb{{_gkek*oi{}Uo|ob_0u2v*bh}}UiS:=?;hlppZdra&ceyQmotv\bl`h'`dxxRjr`o\5r7u'me~xRlP8228mkusWkb#d`|t^`lqqYaaoe$ec}{_erqehY68x$hb{{_c]:6a=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!xe^c274=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\`utfeV;|=!xe^c2[VQ7:l1bb~zPbtk,mkusWke~xRhffn-jjvrXlyxjaR?x1s-taZgX8:;0ec}{_cwj+lht|VhdyyQiigm,mkusWzseoRhffn]`pwj(mdzu>74ioqw[gsn'`dxxRl`uu]emci(agyS~wac^djbjYd|{f$jdh`_qpf[cskd::0ec}{_cwj+lht|VhdyyQiigm,mkusWzseoRhffn]`pwj(n|fg?<5fnrv\fpo(agySoazt^djbj)nfz~Tt`l_gkekZesze%{^1>1309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPsxl`[coagVi~a!R=3=74=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\w|hdWocmcRm{rm-sV949;81bb~zPbtk,mkusWke~xRhffn-jjvrX{pdhSkgio^awvi)wZ595?=5fnrv\fpo(agySoazt^djbj)nfz~Tt`l_gkekZesze%{^R><0:kmwqYe}`%bb~zPbnww[coag&ceyQ|yoa\bl`hWj~y`"~]_013?lht|Vh~e"gasu]akprXn`ld#d`|t^qzjfYaaoeToy|c/qP\6661bb~zPbtk,mkusWke~xRhffn-jjvrX{pdhSkgio^awvi)wZVdnty2?>014?lht|Vh~e"gasu]akprXn`ld#d`|t^qzjfYaaoeToy|c/qP\j`~s484:?:5fnrv\fpo(agySoazt^djbj)nfz~Tt`l_gkekZesze%{^R`jxu>1:4503`dxxRlzi.kmwqYeg|~Tjdh`/hlppZu~fjUmekaPcupo+uTXflr0>0>399jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPsxl`[coagVi~a!R^lf|q:468;8m6gasu]aql)nfz~Tnb{{_gkek*oi{}UxucmPfhdl[frud&zYSckwt=1=5Z`2;81bb~zPbtk,mkusWke~xRhffn-jjvrX{pdhSkgio^awvi)w_5:5?<5fnrv\fpo(agySoazt^djbj)nfz~Tt`l_gkekZesze%{[1?1309jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPsxl`[coagVi~a!W=0=74=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\w|hdWocmcRm{rm-sS959;91bb~zPbtk,mkusWke~xRhffn-jjvrX{pdhSkgio^awvi)w_V:8<6gasu]aql)nfz~Tnb{{_gkek*oi{}UxucmPfhdl[frud&z\S<=?;hlppZdra&ceyQmotv\bl`h'`dxxR}vnb]emciXk}xg#}YP2228mkusWkb#d`|t^`lqqYaaoe$ec}{_r{mgZ`nnfUhxb pV]073=nfz~Tnxg ioqw[gir|Vlbjb!fnrv\w|hdWocmcRm{rm-sSZhbp}6;2>94ioqw[gsn'`dxxRl`uu]emci(agyS~wac^djbjYd|{f$|ZQaeyv?4;74>2ceyQmuh-jjvrXjfSkgio.kmwqYtqgiTjdh`_bvqh*vPWgosx1?1369jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPsxl`[coagVi~a!W^lf|q:6689=7d`|t^`vm*oi{}UicxzPfhdl+lht|VyrbnQiigm\gqtk'y]Tbhv{<3<03>oi{}Uiyd!fnrv\fjssWocmc"gasu]p}keXn`ldSnz}l.rT[kc|585=>84ioqw[gsn'`dxxRl`uu]emci(agyS~wac^djbjYd|{f$|ZQaeyv?7;503`dxxRlzi.kmwqYeg|~Tjdh`/hlppZu~fjUmekaPcupo+uQXflr0>0>399jjvrXj|c$ec}{_cmvpZ`nnf%bb~zPsxl`[coagVi~a!W^lf|q:468;846gasu]aql)nfz~Tnb{{_gkek*oi{}UxucmPfhdl[frud&z\Sckwt=1=575f3`dxxRlzi.kmwqYeg|~Tjdh`/hlppZu~fjUmekaPcupo+uQXflr0>0>_g70b>oi{}Uiyd!fnrv\fjssWocmc"gasu]p}keXn`ldSnz}l.rqaZcjx}sTmcj?012126`oi{}Uiyd!fnrv\fjssWocmc"gasu]p}keXn`ldSnz}l.ubwZqua}o8h6gasu]aql)nfz~Tnb{{_gkek*oi{}UxucmPfhdl[frud&}jRy}iug\jjr789;8i6gasu]aql)nfz~Tnb{{_gkek*oi{}UxucmPfhdl[frud&}jRy}iug\jjr789;:><5fnrv\fpo(agySoazt^djbj)jmdUyhRka239jjvrXj|c$ec}{_cmvpZ`nnf%fi`Q}d^gm577=5fnrv\fpo(agySoazt^djbj)w|{Uy0<0=0:kmwqYe}`%bb~zPbnww[coag&z~R|32?03?lht|Vh~e"gasu]akprXn`ld#}z}_s>0:4e3=8;hlppZdra&ceyQkc`aka*Kdgdzj~Rzng^obpfnXkdzTi|>?01]`}959;>1bb~zPbtk,mkusWmijoek MbmntdtX|hmTalzlh^antZcv89:;Snw34?14?lht|Vh~e"gasu]ggdeom&Ghc`~nr^vbcZkf|jbTo`~Pep2345Ydq5?5?:5fnrv\fpo(agySimncig,IfijxhxTxliPm`v`lZejxVoz<=>?_b{?2;503`dxxRlzi.kmwqYckhici"ClolrbvZrfoVgjxnfPclr\at6789Uhu191369jjvrXj|c$ec}{_eabgmc(Ejef|l|Pt`e\idrd`Vif|Rk~0123[f;07937d`|t^`vm*oi{}Uoolmge.O`khvfzV~jkRcntbj\ghvXmx:;<=Qcuu>3:6>Pltv?7;5?3`dxxRlzi.kmwqYckhici"ClolrbvZrfoVgjxnfPclr\at6789Ugyy2;>2:8mkusWkb#d`|t^f`efnb'Dida}o}_ucd[hgskaUha}Qjq1234Zjr|5?5?55fnrv\fpo(agySimncig,IfijxhxTxliPm`v`lZejxVoz<=>?_mww838402ceyQmuh-jjvrXljkhdh!BcnosewYsinUfmymg_bos[`w789:T`xz37?1;?lht|Vh~e"gasu]ggdeom&Ghc`~nr^vbcZkf|jbTo`~Pep2345Yk}}632>=4ioqw[gsn'`dxxRjlabjf+Heh}g~Tolmge^km``~XkfexRmv<1<02>oi{}Uiyd!fnrv\`fgd`l%Fob{at^abgmcXagnntRm`uov\g|:76Vx?>5fnrv\fpo(agySimncig,Ifirf}Uhmnfj_hlga}Ydg|dSnw31?10?lht|Vh~e"gasu]ggdeom&Ghcx`{_bc`l`YnfmosSnaznu]`}949;:1bb~zPbtk,mkusWmijoek MbmvjqYdijbnSd`key]`kphsWjs7?3=<;hlppZdra&ceyQkc`aka*Kdg|dSnolhd]jjacWje~byQly=6=76=nfz~Tnxg ioqw[aefkao$Anaznu]`efnbW`doiuQlotlw[f;=7987d`|t^`vm*oi{}Uoolmge.O`kphsWjkhdhQfneg{[firf}Uhu181329jjvrXj|c$ec}{_eabgmc(Eje~byQlabjf[lhcmqUhcx`{_b{?3;533`dxxRlzi.kmwqYckhici"Clotlw[fgd`lUbbikw_bmvjqYk}}6:2>o4ioqw[gsn'`dxxRjlabjf+Heh}g~Tolmge^km``~XkfexRbzt=3=[LHQW99?7d`|t^`vm*oi{}Uoolmge.O`kphsWjkhdhQfneg{[firf}Ugyy2=>2c8mkusWkb#d`|t^f`efnb'DidyczPc`akaZoillrTob{at^nvp949W@D]S==;;hlppZdra&ceyQkc`aka*Kdg|dSnolhd]jjacWje~byQcuu>0:6g2>o4ioqw[gsn'`dxxRjlabjf+Heh}g~Tolmge^km``~XkfexRbzt=7=[LHQW99?7d`|t^`vm*oi{}Uoolmge.O`kphsWjkhdhQfneg{[firf}Ugyy29>2c8mkusWkb#d`|t^f`efnb'DidyczPc`akaZoillrTob{at^nvp909W@D]S==;;hlppZdra&ceyQkc`aka*Kdg|dSnolhd]jjacWje~byQcuu>4:6g:4ioqw[gsn'`dxxRjlabjf+Heh}g~Tolmge^km``~XkfexRv`r=3=71=nfz~Tnxg ioqw[aefkao$Anaznu]`efnbW`doiuQlotlw[}iu4;4886gasu]aql)nfz~Thnolhd-Ngjsi|VijoekPioff|Zeh}g~Ttb|33?17?lht|Vh~e"gasu]ggdeom&Ghcx`{_bc`l`YnfmosSnaznu]{kw:36:>0ec}{_cwj+lht|Vnhmnfj/LalqkrXkhiciRgaddz\gjsi|Vrd~1;1359jjvrXj|c$ec}{_eabgmc(Eje~byQlabjf[lhcmqUhcx`{_ymq8384<2ceyQmuh-jjvrXljkhdh!BcnwmpZefkaoTecjjx^alqkrXpfx7;3=;;hlppZdra&ceyQkc`aka*Kdg|dSnolhd]jjacWje~byQwos>;:6g0ec}{_cwj+lht|Vnhmnfj/LalqkrXelgTecjjx^alqkrXpfx7>3?>3`9jjvrXj|c$ec}{_eabgmc(Eje~byQ}al]jjacWje~byQwos>3:47XAG\T<>:4ioqw[gsn'`dxxRjlabjf+Heh}g~T~lcPioff|Zeh}g~Ttb|31?3271=nfz~Tnxg ioqw[aefkao$Anaznu]qehYnfmosSnaznu]{kw:568;:;6gasu]aql)nfz~Thnolhd-M34ce:kmwqYe}`%bb~zPdbc`l`)Umzgx1<11g9jjvrXj|c$ec}{_eabgmc(Zly~`y2=>03e?lht|Vh~e"gasu]ggdeom&Xnxb{<3<15`=nfz~Tnxg ioqw[aefkao$^h}zlu>0:4coi{}Uiyd!fnrv\`fgd`l%hmnfj_dlwv|YnfV~jk1??>00a?lht|Vh~e"gasu]ggdeom&ijoekPeovq}ZoiW}kl0o5fnrv\fpo(agySimncig,gdeomVoexwPio]web:6;78h7d`|t^`vm*oi{}Uoolmge.abgmcXmg~yuRga_ucd84599;h0ec}{_cwj+lht|Vnhmnfj/bc`l`Ybf}xrSd`Pt`e?5185k2ceyQmuh-jjvrXljkhdh!labjf[`hszpUbbRzng=37:44e3`dxxRlzi.kmwqYckhici"mncig\akruqVceSyoh<07=6f=nfz~Tnxg ioqw[aefkao$olmge^gmpwXagUmj2>5?31f>oi{}Uiyd!fnrv\`fgd`l%hmnfj_dlwv|YnfV~jk1?9>3a8mkusWkb#d`|t^f`efnb'jkhdhQjnupz[lhX|hm7=;0>2c9jjvrXj|c$ec}{_eabgmc(khiciRkats{\mkYsin6:;31:7doi{}Uiyd!fnrv\`fgd`l%hmnfj_dlwv|YnfV~jk1=12c9jjvrXj|c$ec}{_eabgmc(khiciRkats{\mkYsin682<3`8mkusWkb#d`|t^f`efnb'jkhdhQjnupz[lhX|hm7:3?=a:kmwqYe}`%bb~zPdbc`l`)dijbnSh`{rx]jjZrfo5=5>o5fnrv\fpo(agySimncig,gdeomVoexwPio]web:0688j7d`|t^`vm*oi{}Uoolmge.abgmcXmg~yuRga_ucd8=85j2ceyQmuh-jjvrXljkhdh!labjf[`hszpUbbRzng=:=57g1d9jjvrXj|c$ec}{_eabgmc(khiciRfft0d8mkusWkb#d`|t^f`efnb'jkhdhQgiu317>oi{}Uiyd!fnrv\`fgd`l%hmnfj_ikw5ZUP8;30ec}{_cwj+lht|Vnhmnfj/bc`l`YnfmosSnaznu>3:7?>3;8mkusWkb#d`|t^f`efnb'jkhdhQfneg{[firf}692?74ioqw[gsn'`dxxRjlabjf+fgd`lUbbikw_bmvjq:46;30ec}{_cwj+lht|Vnhmnfj/bc`l`YnfmosSnaznu>7:7?3;8mkusWkb#d`|t^f`efnb'jkhdhQfneg{[firf}6=2?74ioqw[gsn'`dxxRjlabjf+fgd`lUbbikw_bmvjq:06;30ec}{_cwj+lht|Vnhmnfj/bc`l`YnfmosSnaznu>;:7>55fnrv\fpo(agySimncig,gdeomVcehhvPcnwmpZ3502ceyQmuh-jjvrXljkhdh!labjf[lhcmqUhcx`{_70;?lht|Vh~e"gasu]ggdeom&ijoekPioff|Zeh}g~T;?64ioqw[gsn'`dxxRjlabjf+fgd`lUbbikw_bmvjqY?:m1bb~zPbtk,mkusWmijoek c`akaZoillrTob{at^gm[lhq;=1bb~zPbtk,mkusWmijoek c`akaZoillrTob{at^gm[lhq9VCEZR>=e:kmwqYe}`%bb~zPdbc`l`)dijbnSd`key]`kphsWge<=>?2g9jjvrXj|c$ec}{_eabgmc(khiciRgaddz\gjsi|Vddx=>?0004?lht|Vh~e"gasu]ggdeom&ijoekPioff|Ztbo5:5>:5fnrv\fpo(agySimncig,gdeomVcehhvPrde?5;403`dxxRlzi.kmwqYckhici"mncig\mkbbpVxnk1<1269jjvrXj|c$ec}{_eabgmc(khiciRgaddz\v`a;;78<7d`|t^`vm*oi{}Uoolmge.abgmcXagnntR|jg=6=62=nfz~Tnxg ioqw[aefkao$olmge^km``~Xzlm793<8;hlppZdra&ceyQkc`aka*efkaoTecjjx^pfc909:>1bb~zPbtk,mkusWmijoek c`akaZoillrT~hi37?04?lht|Vh~e"gasu]ggdeom&ijoekPioff|Ztbo525>;5fnrv\fpo(agySimncig,gdeomVcehhvPrde\4702ceyQmuh-jjvrXljkhdh!labjf[lhcmqUyijQ<279jjvrXj|c$ec}{_eabgmc(khiciRgaddz\v`aX<;<0ec}{_cwj+lht|Vnhmnfj/bc`l`YnfmosSkh_405?lht|Vh~e"gasu]ggdeom&ijoekPioff|ZtboV<9:6gasu]aql)nfz~Thnolhd-`efnbW`doiuQ}ef]463=nfz~Tnxg ioqw[aefkao$olmge^km``~XzlmT4?m4ioqw[gsn'`dxxRjlabjf+fgd`lUbbikw_sgd[dhc89:;>i5fnrv\fpo(agySimncig,gdeomVcehhvPrde\ekb789::?<5fnrv\fpo(agySimncig,gdeomVcehhvPrde\ekb789::S^Y?2e9jjvrXj|c$ec}{_eabgmc(khiciRgaddz\v`aXign;<=>=239jjvrXj|c$ec}{_eabgmc(kyTnhQ}ef>3:74<5fnrv\fpo(agySimncig,gusXjlUyijQ=209jjvrXj|c$ec}{_eabgmc(kyTnhQ}ef]062=nfz~Tnxg ioqw[aefkao$o}{Pbd]qabYig}:;<;hlppZdra&ceyQkc`aka*ew}Vh~tQ\W106?lht|Vh~e"gasu]ggdeom&i{yRj}al]b`at;878=7d`|t^`vm*oi{}Uoolmge.asqZbuidUjhi|30?312>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\eabu48:5>:5fnrv\fpo(agySimncig,gusXl{kfSljkr=33:4413`dxxRlzi.kmwqYckhici"mu^fqehYflmx7=<0=7:kmwqYe}`%bb~zPdbc`l`)dx|Uo~lcPaefq84799;?0ec}{_cwj+lht|Vnhmnfj/brv[atfeVkoh2>>348mkusWkb#d`|t^f`efnb'jz~Si|nm^cg`w:6688>7d`|t^`vm*oi{}Uoolmge.asqZbuidUjhi|32?05?lht|Vh~e"gasu]ggdeom&i{yRj}al]b`at;:7;996gasu]aql)nfz~Thnolhd-`tpYczhgTmij}<2<12>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\eabu4:4:>85fnrv\fpo(agySimncig,gusXl{kfSljkr=6=63=nfz~Tnxg ioqw[aefkao$o}{Pdscn[dbcz5>5=?;4ioqw[gsn'`dxxRjlabjf+fvrWmxjaRokds>6:702<<:;hlppZdra&ceyQkc`aka*ew}Vnym`Qndep?2;413`dxxRlzi.kmwqYckhici"mu^fqehYflmx7:3?=5:kmwqYe}`%bb~zPdbc`l`)dx|Uo~lcPaefq8285>2ceyQmuh-jjvrXljkhdh!lpt]gvdkXimny0:0>249jjvrXj|c$ec}{_eabgmc(kyThob_`fgv9>9:?1bb~zPbtk,mkusWmijoek cqw\`wgjWhno~1611378mkusWkb#d`|t^f`efnb'jz~Si|nm^cg`w:>6;<0ec}{_cwj+lht|Vnhmnfj/brv[atfeVkoh26>00b?lht|Vh~e"gasu]ggdeom&i{yRj}al]b`atXign;<=>=b:kmwqYe}`%bb~zPdbc`l`)dx|Uo~lcPaefq[dhc89:;=?:4ioqw[gsn'`dxxRjlabjf+fvrWmxjaRjfn=2=60=nfz~Tnxg ioqw[aefkao$o}{Pdscn[aoi48:5>85fnrv\fpo(agySimncig,gusXl{kfSiga<03=60=nfz~Tnxg ioqw[aefkao$o}{Pdscn[aoi4885>85fnrv\fpo(agySimncig,gusXl{kfSiga<01=60=nfz~Tnxg ioqw[aefkao$o}{Pdscn[aoi48>5>85fnrv\fpo(agySimncig,gusXl{kfSiga<07=60=nfz~Tnxg ioqw[aefkao$o}{Pdscn[aoi48<5>85fnrv\fpo(agySimncig,gusXl{kfSiga<05=60=nfz~Tnxg ioqw[aefkao$o}{Pdscn[aoi4825>85fnrv\fpo(agySimncig,gusXl{kfSiga<0;=61=nfz~Tnxg ioqw[aefkao$o}{Pdscn[aoi484996gasu]aql)nfz~Thnolhd-`tpYczhgThd`321<11>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\`lh;:84996gasu]aql)nfz~Thnolhd-`tpYczhgThd`323<11>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\`lh;::4996gasu]aql)nfz~Thnolhd-`tpYczhgThd`325<11>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\`lh;:<4996gasu]aql)nfz~Thnolhd-`tpYczhgThd`327<11>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\`lh;:>4996gasu]aql)nfz~Thnolhd-`tpYczhgThd`329<11>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\`lh;:04986gasu]aql)nfz~Thnolhd-`tpYczhgThd`32?06?lht|Vh~e"gasu]ggdeom&i{yRj}al]gmk:4878>7d`|t^`vm*oi{}Uoolmge.asqZbuidUoec2<1?07?lht|Vh~e"gasu]ggdeom&i{yRj}al]gmk:46;>0ec}{_cwj+lht|Vnhmnfj/brv[atfeVnbb1:1259jjvrXj|c$ec}{_eabgmc(kyThob_ekm8085<2ceyQmuh-jjvrXljkhdh!lpt]gvdkXl`d7:3<;;hlppZdra&ceyQkc`aka*ew}Vnym`Qkio>4:7295fnrv\fpo(agySimncig,gusXl{kfSiga<8<17>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\`lhX8;90ec}{_cwj+lht|Vnhmnfj/brv[atfeVnbbR?=4:kmwqYe}`%bb~zPdbc`l`)dx|Uo~lcPdhl\55433`dxxRlzi.kmwqYckhici"mu^fqehYcagU:=?:4ioqw[gsn'`dxxRjlabjf+fvrWmxjaRjfn^3161=nfz~Tnxg ioqw[aefkao$o}{Pdscn[aoiW89986gasu]aql)nfz~Thnolhd-`tpYczhgThd`P1507?lht|Vh~e"gasu]ggdeom&i{yRj}al]gmkY6=;>0ec}{_cwj+lht|Vnhmnfj/brv[atfeVnbbR?9259jjvrXj|c$ec}{_eabgmc(kyThob_ekm[415<2ceyQmuh-jjvrXljkhdh!lpt]gvdkXl`dT=5<;;hlppZdra&ceyQkc`aka*ew}Vnym`Qkio]2=750ec}{_cwj+lht|Vnhmnfj/brv[atfeVnbbR<=259jjvrXj|c$ec}{_eabgmc(kyThob_ekm[755<2ceyQmuh-jjvrXljkhdh!lpt]gvdkXl`dT>9<;;hlppZdra&ceyQkc`aka*ew}Vnym`Qkio]117295fnrv\fpo(agySimncig,gusXl{kfSiga_3510>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\`lhX:18?7d`|t^`vm*oi{}Uoolmge.asqZbuidUoecQ=9318mkusWkb#d`|t^f`efnb'jz~Si|nm^fjjZ55<2ceyQmuh-jjvrXljkhdh!lpt]gvdkXl`dT?=<;;hlppZdra&ceyQkc`aka*ew}Vnym`Qkio]05759?6gasu]aql)nfz~Thnolhd-`tpYczhgThd`P5318mkusWkb#d`|t^f`efnb'jz~Si|nm^fjjZ05;2ceyQmuh-jjvrXljkhdh!lpt]gvdkXl`dT;?=4ioqw[gsn'`dxxRjlabjf+fvrWmxjaRjfn^:17>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\`lhX1;90ec}{_cwj+lht|Vnhmnfj/brv[atfeV}n0=0=4:kmwqYe}`%bb~zPdbc`l`)dx|Uo~lcPwd>3:4443`dxxRlzi.kmwqYckhici"mu^fqehYpm5;5>95fnrv\fpo(agySimncig,gusXl{kfSzk31?317>oi{}Uiyd!fnrv\`fgd`l%h|xQkr`o\s`:56;>0ec}{_cwj+lht|Vnhmnfj/brv[atfeV}n0?0>229jjvrXj|c$ec}{_eabgmc(kyThob_vg?7;433`dxxRlzi.kmwqYckhici"mu^fqehYpm595=<5fnrv\fpo(agySimncig,gusXzlmTic<>1b9jjvrXj|c$ec}{_eabgmc(kyT{h<=4:kmwqYe}`%bb~zPdbc`l`)dx|U|i?Qnne2345423`dxxRlzi.kmwqYckhici"mu^uf6Zgil9:;<<<7;hlppZdra&ceyQkc`aka*ew}V}n>Road1234Zoi~;30ec}{_cwj+lht|Vnhmnfj/brv[rc5Whdo<=>?_hlu54`?0338mkusWkb#d`|t^f`efnb'j~y`Rj}al]fj74R.hlppZbf|hUym`!Br`o\VDK5;j1bb~zPbtk,mkusWmijoek gdl\`drfW{kfWoi{}Uiyd!fnrv\`fgd`l%licQkauc\vdk\;T$bb~zPd`vb[wgj'DxjaR\NM30b?lht|Vh~e"gasu]ggdeom&ceyQ{af]qeh)JzhgT^LC=8:kmwqYe}`%bb~zPdbc`l`)nfz~TxliPr`o,s`YfW98;7d`|t^`vm*oi{}Uoolmge.kmwqgi|Vxj{?74ioqw[gsn'`dxxRjlabjf+lht|hdSox_`lg45679;=0ec}{_cwj+lht|Vnhmnfj/lgn[lhcmqUhcx`{<1<13>oi{}Uiyd!fnrv\`fgd`l%fi`Qfneg{[firf}6:2?94ioqw[gsn'`dxxRjlabjf+hcjW`doiuQlotlw8785>2ceyQmuh-jjvrXljkhdh!bel]jjacWje~byQ?279jjvrXj|c$ec}{_eabgmc(elgTecjjx^alqkrX9;<0ec}{_cwj+lht|Vnhmnfj/lgn[lhcmqUhcx`{_30`?lht|Vh~e"gasu]ggdeom&gnaRgaddz\gjsi|Vddx=>?13f8mkusWkb#d`|t^f`efnb'dofSd`key]`kphsWge<=>>1358mkusWkb#d`|t^f`efnb'{kfSd`key]`kphs4949;6gasu]aql)nfz~Thnolhd-qehYnfmosSnaznu>2:71?<4ioqw[gsn'`dxxRjlabjf+vYA[DUMJi<"Io00?lht|Vh~e"gasu]ggdeom&yTJ^CPFGf1)Lh69o1bb~zPbtk,mkusWmijoek s^DPIZ@Al:887d`|t^`vm*oi{}Uoolmge.q\BVKXNOn8!D`>279jjvrXj|c$ec}{_eabgmc({VLXARHId2/JjZUP88l0ec}{_cwj+lht|Vnhmnfj/r]EWHYANm>9>6gasu]aql)nfz~Thnolhd-p[CUJWOLo8 Ga229jjvrXj|c$ec}{_eabgmc({VLXARHId5/Jj47a3`dxxRlzi.kmwqYckhici"}PFRO\BCb2:;1bb~zPbtk,mkusWmijoek s^DPIZ@Al<'Bb?84ioqw[gsn'`dxxRjlabjf+vYA[DUMJi;"Io]PS5413`dxxRlzi.kmwqYckhici"}PFRO\BCb2%@dT_Z?>f:kmwqYe}`%bb~zPdbc`l`)tWOYFSKHk6308mkusWkb#d`|t^f`efnb'zUM_@QIFe4.Mk413`dxxRlzi.kmwqYckhici"}PFRO\BCb1%@dT_Z>>f:kmwqYe}`%bb~zPdbc`l`)tWOYFSKHk7328mkusWkb#d`|t^f`efnb'zUM_@Q@uu:264=nfz~Tnxg ioqw[aefkao$Rmbp^gr4567::1bb~zPbtk,mkusWmijoek s^antZcv89:;=:<;;hlppZdra&ceyQkc`aka*uXkdzTi|>?0134570?011166=nfz~Tnxg ioqw[aefkao$Rmbp^gr4567;:8:7d`|t^`vm*oi{}Uoolmge.q\ghvXmx:;<<<=;hlppZdra&ceyQkc`aka*uXkdzTi|>?00315>oi{}Uiyd!fnrv\`fgd`l%xSnc_ds34545:2ceyQmuh-jjvrXljkhdh!|_bos[`w7898:>85fnrv\fpo(agySimncig,pdaXagnntR|jg=2=63=nfz~Tnxg ioqw[aefkao$xliPioff|Ztbo5;;2?84ioqw[gsn'`dxxRjlabjf+qg`W`doiuQ}ef>25;413`dxxRlzi.kmwqYckhici"zng^km``~Xzlm7=?0=6:kmwqYe}`%bb~zPdbc`l`)sinUbbikw_sgd8459:?1bb~zPbtk,mkusWmijoek t`e\mkbbpVxnk1?;>348mkusWkb#d`|t^f`efnb'}klSd`key]qab:6=78=7d`|t^`vm*oi{}Uoolmge.vbcZoillrT~hi317<12>oi{}Uiyd!fnrv\`fgd`l%mjQfneg{[wc`48=5>85fnrv\fpo(agySimncig,pdaXagnntR|jg=3=60=nfz~Tnxg ioqw[aefkao$xliPioff|Ztbo585>85fnrv\fpo(agySimncig,pdaXagnntR|jg=1=60=nfz~Tnxg ioqw[aefkao$xliPioff|Ztbo5>5>85fnrv\fpo(agySimncig,pdaXagnntR|jg=7=60=nfz~Tnxg ioqw[aefkao$xliPioff|Ztbo5<5>85fnrv\fpo(agySimncig,pdaXagnntR|jg=5=60=nfz~Tnxg ioqw[aefkao$xliPioff|Ztbo525>85fnrv\fpo(agySimncig,pdaXagnntR|jg=;=61=nfz~Tnxg ioqw[aefkao$xliPioff|ZtboV:986gasu]aql)nfz~Thnolhd-webYnfmosSkh_006?lht|Vh~e"gasu]ggdeom&~jkRgaddz\v`aX998>7d`|t^`vm*oi{}Uoolmge.vbcZoillrT~hiP1006?lht|Vh~e"gasu]ggdeom&~jkRgaddz\v`aX9;8>7d`|t^`vm*oi{}Uoolmge.vbcZoillrT~hiP1206?lht|Vh~e"gasu]ggdeom&~jkRgaddz\v`aX9=8>7d`|t^`vm*oi{}Uoolmge.vbcZoillrT~hiP1406?lht|Vh~e"gasu]ggdeom&~jkRgaddz\v`aX9?8>7d`|t^`vm*oi{}Uoolmge.vbcZoillrT~hiP1607?lht|Vh~e"gasu]ggdeom&~jkRgaddz\v`aX:;>0ec}{_cwj+lht|Vnhmnfj/ucd[lhcmqUyijQ<259jjvrXj|c$ec}{_eabgmc(|hmTecjjx^pfcZ25<2ceyQmuh-jjvrXljkhdh!{af]jjacW{olS8<;;hlppZdra&ceyQkc`aka*rfoVcehhvPrde\27295fnrv\fpo(agySimncig,pdaXagnntR|jg^:10>oi{}Uiyd!fnrv\`fgd`l%mjQfneg{[wc`W08?7d`|t^`vm*oi{}Uoolmge.vqehYflmxT~i2?>378mkusWkb#d`|t^f`efnb'}xjaRokds]q`9699;>0ec}{_cwj+lht|Vnhmnfj/upbiZgcl{Uyh1?1249jjvrXj|c$ec}{_eabgmc(|{kfSljkr^pg8486:=1bb~zPbtk,mkusWmijoek tscn[dbczVxo0?0=5:kmwqYe}`%bb~zPdbc`l`)szhgTmij}_sf?6;75<2ceyQmuh-jjvrXljkhdh!{r`o\eabuW{n7?3<:;hlppZdra&ceyQkc`aka*ruidUjhi|Pre>0:4433`dxxRlzi.kmwqYckhici"z}al]b`atXzm6?2?;4ioqw[gsn'`dxxRjlabjf+qtfeVkohQ}d=6=57285fnrv\fpo(agySimncig,pwgjWhno~R|k<4<261=nfz~Tnxg ioqw[aefkao$xob_`fgvZtc4?4996gasu]aql)nfz~Thnolhd-wvdkXimnySj36?310>oi{}Uiyd!fnrv\`fgd`l%~lcPaefq[wb;?78>7d`|t^`vm*oi{}Uoolmge.vqehYflmxT~i28>007?lht|Vh~e"gasu]ggdeom&~ym`Qndep\va:?6;?0ec}{_cwj+lht|Vnhmnfj/upbiZgcl{Uyh1611368mkusWkb#d`|t^f`efnb'}xjaRokds]tv969:<1bb~zPbtk,mkusWmijoek tscn[dbczV}y0=0>259jjvrXj|c$ec}{_eabgmc(|{kfSljkr^uq8485=2ceyQmuh-jjvrXljkhdh!{r`o\eabuW~x7=3?=4:kmwqYe}`%bb~zPdbc`l`)szhgTmij}_vp?6;423`dxxRlzi.kmwqYckhici"z}al]b`atX{692<<;;hlppZdra&ceyQkc`aka*ruidUjhi|Pws>0:7395fnrv\fpo(agySimncig,pwgjWhno~Ry}<4<11>oi{}Uiyd!fnrv\`fgd`l%~lcPaefq[rt;=7;986gasu]aql)nfz~Thnolhd-wvdkXimnySz|36?06?lht|Vh~e"gasu]ggdeom&~ym`Qndep\sw:1688?7d`|t^`vm*oi{}Uoolmge.vqehYflmxT{28>378mkusWkb#d`|t^f`efnb'}xjaRokds]tv9199;>0ec}{_cwj+lht|Vnhmnfj/upbiZgcl{U|~161249jjvrXj|c$ec}{_eabgmc(|{kfSljkr^uq8=86:81bb~zPbtk,mkusWmijoek tscn[air|5:5>?5fnrv\fpo(agySimncig,pwgjWme~x1??>308mkusWkb#d`|t^f`efnb'}xjaRj`uu>25;453`dxxRlzi.kmwqYckhici"z}al]gkpr;9;49>6gasu]aql)nfz~Thnolhd-wvdkXlf0<=1239jjvrXj|c$ec}{_eabgmc(|{kfSiazt=37:74oi{}Uiyd!fnrv\`fgd`l%~lcPdnww8779:81bb~zPbtk,mkusWmijoek tscn[air|5>5><5fnrv\fpo(agySimncig,pwgjWme~x1;1209jjvrXj|c$ec}{_eabgmc(|{kfSiazt=4=64=nfz~Tnxg ioqw[aefkao$xob_emvp919:81bb~zPbtk,mkusWmijoek tscn[air|525><5fnrv\fpo(agySimncig,pwgjWme~x1711b9jjvrXj|c$ec}{_eabgmc(|{kfSk>d:kmwqYe}`%bb~zPdbc`l`)szhgT~h?=6:kmwqYe}`%bb~zPdbc`l`)pg{nTecjjx^pfc969:?1bb~zPbtk,mkusWmijoek wnpg[lhcmqUyij2>>348mkusWkb#d`|t^f`efnb'~eyhRgaddz\v`a;:78>7d`|t^`vm*oi{}Uoolmge.ulvaYnfmosSkh_106?lht|Vh~e"gasu]ggdeom&}d~iQfneg{[wc`W88>7d`|t^`vm*oi{}Uoolmge.ulvaYnfmosSkh_30a?lht|Vh~e"gasu]ggdeom&}d~iQfneg{[wc`Wge<=>>2b9jjvrXj|c$ec}{_eabgmc(fxoSd`key]qabYig}:;<a:kmwqYe}`%bb~zPibc`l`)DQJUD=h5fnrv\fpo(agySdmncig,G\EXGVY\=>94ioqw[gsn'`dxxRglabjf+HeheykySyoh_lcwgmYdeyUn}=>?0^az8584?2ceyQmuh-jjvrXajkhdh!BcnosewYsinUfmymg_bos[`w789:Tot2>>258mkusWkb#d`|t^k`efnb'Dida}o}_ucd[hgskaUha}Qjq1234Ze~4;48;6gasu]aql)nfz~Tenolhd-Ngjkwi{UmjQbauak[fkwWl{;<=>Pcx>0:61oi{}Uiyd!fnrv\mfgd`l%Fobcas]webYji}icSnc_ds3456Xkp6<2>94ioqw[gsn'`dxxRglabjf+HeheykySyoh_lcwgmYdeyUn}=>?0^az8=8402ceyQmuh-jjvrXajkhdh!BcnosewYsinUfmymg_bos[`w789:T`xz30?1;?lht|Vh~e"gasu]jgdeom&Ghc`~nr^vbcZkf|jbTo`~Pep2345Yk}}6:2>64ioqw[gsn'`dxxRglabjf+HeheykySyoh_lcwgmYdeyUn}=>?0^nvp949;11bb~zPbtk,mkusW`ijoek MbmntdtX|hmTalzlh^antZcv89:;Sa{{<2<0<>oi{}Uiyd!fnrv\mfgd`l%Fobcas]webYji}icSnc_ds3456Xd|~783=7;hlppZdra&ceyQfc`aka*Kdgdzj~Rzng^obpfnXkdzTi|>?01]oqq:26:20ec}{_cwj+lht|Vchmnfj/LaliuguW}klS`o{ci]`iuYby9:;1379jjvrXj|c$ec}{_habgmc(Eje~byQlabjf[lhcmqUhcx`{_b{?4;Yu|:90ec}{_cwj+lht|Vchmnfj/LalqkrXkhiciRgaddz\gjsi|Vir0<0<3:kmwqYe}`%bb~zPibc`l`)JkfexRmncig\mkbbpVidyczPcx>1:65218mkusWkb#d`|t^k`efnb'DidyczPc`akaZoillrTob{at^az8084;2ceyQmuh-jjvrXajkhdh!BcnwmpZefkaoTecjjx^alqkrXkp6=2>=4ioqw[gsn'`dxxRglabjf+Heh}g~Tolmge^km``~XkfexRmv<6<00>oi{}Uiyd!fnrv\mfgd`l%Fob{at^abgmcXagnntRm`uov\hpr;979j7d`|t^`vm*oi{}Ubolmge.O`kphsWjkhdhQfneg{[firf}Ugyy2>>^KMRZ64<2ceyQmuh-jjvrXajkhdh!BcnwmpZefkaoTecjjx^alqkrXd|~7>3=n;hlppZdra&ceyQfc`aka*Kdg|dSnolhd]jjacWje~byQcuu>1:ZOI^V:886gasu]aql)nfz~Tenolhd-Ngjsi|VijoekPioff|Zeh}g~T`xz33?1b?lht|Vh~e"gasu]jgdeom&Ghcx`{_bc`l`YnfmosSnaznu]oqq:46VCEZR><4:kmwqYe}`%bb~zPibc`l`)JkfexRmncig\mkbbpVidyczPltv?0;5f3`dxxRlzi.kmwqYnkhici"Clotlw[fgd`lUbbikw_bmvjqYk}}6?2RGAV^200>oi{}Uiyd!fnrv\mfgd`l%Fob{at^abgmcXagnntRm`uov\hpr;=79j7d`|t^`vm*oi{}Ubolmge.O`kphsWjkhdhQfneg{[firf}Ugyy2:>^KMRZ64<2ceyQmuh-jjvrXajkhdh!BcnwmpZefkaoTecjjx^alqkrXd|~7:3=n;hlppZdra&ceyQfc`aka*Kdg|dSnolhd]jjacWje~byQcuu>5:ZOI^V:886gasu]aql)nfz~Tenolhd-Ngjsi|VijoekPioff|Zeh}g~T`xz37?1b?lht|Vh~e"gasu]jgdeom&Ghcx`{_bc`l`YnfmosSnaznu]oqq:06VCEZR><4:kmwqYe}`%bb~zPibc`l`)JkfexRmncig\mkbbpVidyczPltv?<;5f3`dxxRlzi.kmwqYnkhici"Clotlw[fgd`lUbbikw_bmvjqYk}}632RGAV^200>oi{}Uiyd!fnrv\mfgd`l%Fob{at^abgmcXagnntRm`uov\|jt;879?7d`|t^`vm*oi{}Ubolmge.O`kphsWjkhdhQfneg{[firf}Usc2>>268mkusWkb#d`|t^k`efnb'DidyczPc`akaZoillrTob{at^zlv949;=1bb~zPbtk,mkusW`ijoek MbmvjqYdijbnSd`key]`kphsWqey0>0<4:kmwqYe}`%bb~zPibc`l`)JkfexRmncig\mkbbpVidyczPxnp?0;533`dxxRlzi.kmwqYnkhici"Clotlw[fgd`lUbbikw_bmvjqYg{6>2>:4ioqw[gsn'`dxxRglabjf+Heh}g~Tolmge^km``~XkfexRv`r=4=71=nfz~Tnxg ioqw[lefkao$Anaznu]`efnbW`doiuQlotlw[}iu4>4886gasu]aql)nfz~Tenolhd-Ngjsi|VijoekPioff|Zeh}g~Ttb|38?1b?lht|Vh~e"gasu]jgdeom&Ghcx`{_lgn[lhcmqUhcx`{_ymq85869VCEZR><4:kmwqYe}`%bb~zPibc`l`)JkfexRcjm^km``~XkfexRv`r=3=54533`dxxRlzi.kmwqYnkhici"Clotlw[hcjW`doiuQlotlw[}iu4;4:=>o4ioqw[gsn'`dxxRglabjf+Heh}g~T~lcPioff|Zeh}g~Ttb|30?32[LHQW99?7d`|t^`vm*oi{}Ubolmge.O`kphsW{kfSd`key]`kphsWqey0<0>1268mkusWkb#d`|t^k`efnb'DidyczPr`o\mkbbpVidyczPxnp?6;76:h1bb~zPbtk,mkusW`ijoek c`akaZci|{sTecQ{af>3:7doi{}Uiyd!fnrv\mfgd`l%hmnfj_dlwv|YnfV~jk1??>3a8mkusWkb#d`|t^k`efnb'jkhdhQjnupz[lhX|hm7==0>2c9jjvrXj|c$ec}{_habgmc(khiciRkats{\mkYsin6:=327;75j2ceyQmuh-jjvrXajkhdh!labjf[`hszpUbbRzng=37:7e5?0`?lht|Vh~e"gasu]jgdeom&ijoekPeovq}ZoiW}kl0<;113`8mkusWkb#d`|t^k`efnb'jkhdhQjnupz[lhX|hm7=;0=c:kmwqYe}`%bb~zPibc`l`)dijbnSh`{rx]jjZrfo5;=2<n5fnrv\fpo(agySdmncig,gdeomVoexwPio]web:6?7;9m6gasu]aql)nfz~Tenolhd-`efnbWld~tQfn^vbc979:k1bb~zPbtk,mkusW`ijoek c`akaZci|{sTecQ{af>2:44f3`dxxRlzi.kmwqYnkhici"mncig\akruqVceSyoh<3<1f>oi{}Uiyd!fnrv\mfgd`l%hmnfj_dlwv|YnfV~jk1<113c8mkusWkb#d`|t^k`efnb'jkhdhQjnupz[lhX|hm7?3l5fnrv\fpo(agySdmncig,gdeomVoexwPio]web:36;h0ec}{_cwj+lht|Vchmnfj/bc`l`Ybf}xrSd`Pt`e?0;75i2ceyQmuh-jjvrXajkhdh!labjf[`hszpUbbRzng=7=6g=nfz~Tnxg ioqw[lefkao$olmge^gmpwXagUmj2:>00b?lht|Vh~e"gasu]jgdeom&ijoekPeovq}ZoiW}kl0;0=b:kmwqYe}`%bb~zPibc`l`)dijbnSh`{rx]jjZrfo5<5=?o4ioqw[gsn'`dxxRglabjf+fgd`lUnby|v_hl\pda;?78i7d`|t^`vm*oi{}Ubolmge.abgmcXmg~yuRga_ucd8286:h1bb~zPbtk,mkusW`ijoek c`akaZci|{sTecQ{af>;:7doi{}Uiyd!fnrv\mfgd`l%hmnfj_dlwv|YnfV~jk1712c9jjvrXj|c$ec}{_habgmc(khiciRkats{\mkYsin622<<6;hlppZdra&ceyQfc`aka*efkaoTecjjx^alqkr;87827d`|t^`vm*oi{}Ubolmge.abgmcXagnntRm`uov?5;4>3`dxxRlzi.kmwqYnkhici"mncig\mkbbpVidycz32?0:?lht|Vh~e"gasu]jgdeom&ijoekPioff|Zeh}g~7?3<6;hlppZdra&ceyQfc`aka*efkaoTecjjx^alqkr;<7827d`|t^`vm*oi{}Ubolmge.abgmcXagnntRm`uov?1;4>3`dxxRlzi.kmwqYnkhici"mncig\mkbbpVidycz36?0:?lht|Vh~e"gasu]jgdeom&ijoekPioff|Zeh}g~7;3<6;hlppZdra&ceyQfc`aka*efkaoTecjjx^alqkr;07837d`|t^`vm*oi{}Ubolmge.abgmcXagnntRm`uov\47>299jjvrXj|c$ec}{_habgmc(khiciRgaddz\gjsi|V8946gasu]aql)nfz~Tenolhd-`efnbW`doiuQlotlw[64?3`dxxRlzi.kmwqYnkhici"mncig\mkbbpVidyczP43:8mkusWkb#d`|t^k`efnb'jkhdhQfneg{[firf}U>>55fnrv\fpo(agySdmncig,gdeomVcehhvPcnwmpZ0502ceyQmuh-jjvrXajkhdh!labjf[lhcmqUhcx`{_60;?lht|Vh~e"gasu]jgdeom&ijoekPioff|Zeh}g~T4?j4ioqw[gsn'`dxxRglabjf+fgd`lUbbikw_bmvjqYbfVcez>:4ioqw[gsn'`dxxRglabjf+fgd`lUbbikw_bmvjqYbfVcez358mkusWkb#d`|t^k`efnb'jkhdhQfneg{[wc`4849;6gasu]aql)nfz~Tenolhd-`efnbW`doiuQ}ef>1:710=7:kmwqYe}`%bb~zPibc`l`)dijbnSd`key]qab:36;=0ec}{_cwj+lht|Vchmnfj/bc`l`YnfmosSkh<4<13>oi{}Uiyd!fnrv\mfgd`l%hmnfj_hlga}Yumn6=2?94ioqw[gsn'`dxxRglabjf+fgd`lUbbikw_sgd8285?2ceyQmuh-jjvrXajkhdh!labjf[lhcmqUyij27>348mkusWkb#d`|t^k`efnb'jkhdhQfneg{[wc`W98=7d`|t^`vm*oi{}Ubolmge.abgmcXagnntR|jg^312>oi{}Uiyd!fnrv\mfgd`l%hmnfj_hlga}YumnU9>;5fnrv\fpo(agySdmncig,gdeomVcehhvPrde\7702ceyQmuh-jjvrXajkhdh!labjf[lhcmqUyijQ9279jjvrXj|c$ec}{_habgmc(khiciRgaddz\v`aX?;<0ec}{_cwj+lht|Vchmnfj/bc`l`YnfmosSkh_904?lht|Vh~e"gasu]jgdeom&ijoekPmhqp[dhc89:;>55fnrv\fpo(agySdmncig,gdeomVgb~Qnne234576n2ceyQmuh-jjvrXajkhdh!lpt]qabYbf;:0ec}{_cwj+lht|Vchmnfj/brv[wc`Wld:>55fnrv\fpo(agySdmncig,`drfW{kfSljkr^pg858512ceyQmuh-jjvrXajkhdh!kauc\vdkXimnySj30?31=>oi{}Uiyd!fnrv\mfgd`l%omyoPr`o\eabuW{n7==0=a:kmwqYe}`%bb~zPibc`l`)ci}kT~lcPaefq[wb;994:>45fnrv\fpo(agySdmncig,`drfW{kfSljkr^pg8479:h1bb~zPbtk,mkusW`ijoek d`vb[wgjWhno~R|k<03=57>55fnrv\fpo(agySdmncig,`drfW{kfSljkr^pg878512ceyQmuh-jjvrXajkhdh!kauc\vdkXimnySj32?31<>oi{}Uiyd!fnrv\mfgd`l%omyoPr`o\eabuW{n7?3<6;hlppZdra&ceyQfc`aka*bf|hUym`Qndep\va:468837d`|t^`vm*oi{}Ubolmge.fbpdYuidUjhi|Pre>7:7?45fnrv\fpo(agySdmncig,`drfW{kfSljkr^pg8086:11bb~zPbtk,mkusW`ijoek d`vb[wgjWhno~R|k<7<1=>oi{}Uiyd!fnrv\mfgd`l%omyoPr`o\eabuW{n7:3?=8:kmwqYe}`%bb~zPibc`l`)ci}kT~lcPaefq[wb;?7827d`|t^`vm*oi{}Ubolmge.fbpdYuidUjhi|Pre>4:44?3`dxxRlzi.kmwqYnkhici"jnt`]qehYflmxT~i27>3;8mkusWkb#d`|t^k`efnb'mkmR|nm^cg`wYul525=?64ioqw[gsn'`dxxRglabjf+agsiVxjaRokds]q`9?9:01bb~zPbtk,mkusW`ijoek d`vb[wgjWhno~R|k<8<265=nfz~Tnxg ioqw[lefkao$hlzn_scn[wc592ceyQmuh-jjvrXajkhdh!kauc\vdkXzl;9>6gasu]aql)nfz~Tenolhd-geqgXzhgT~h?>219jjvrXj|c$ec}{_habgmc(lh~jSob_vg15>oi{}Uiyd!fnrv\mfgd`l%omyoPr`o\s`75k2ceyQmuh-jjvrXajkhdh!fnrv\`drfW{kf#@|nm^PBI44d3`dxxRlzi.kmwqYnkhici"gasu]geqgXzhg$Aob_SCN67eoi{}Uiyd!fnrv\mfgd`l%bb~zPd`vb[wgj'DxjaR\NM40`?lht|Vh~e"gasu]jgdeom&ceyQkauc\vdk(E{kfS_OB63a8mkusWkb#d`|t^k`efnb'`dxxRjnt`]qeh)JzhgT^LC82b9jjvrXj|c$ec}{_habgmc(agySio{a^pbi*KuidUYM@6=a:kmwqYe}`%bb~zPibc`l`)nfz~TxliPr`o,IwgjW[KF>55fnrv\fpo(agySdmncig,mkusW}klSob/vg\eZ65?2ceyQmuh-jjvrXajkhdh!bel]jjacWje~by2?>358mkusWkb#d`|t^k`efnb'dofSd`key]`kphs4849;6gasu]aql)nfz~Tenolhd-nahYnfmosSnaznu>1:702ceyQmuh-jjvrXajkhdh!bel]jjacWje~byQ=2b9jjvrXj|c$ec}{_habgmc(elgTecjjx^alqkrXff~;<=?=d:kmwqYe}`%bb~zPibc`l`)jmdUbbikw_bmvjqYig}:;<oi{}Uiyd!fnrv\mfgd`l%ym`Qfneg{[firf}692?84ioqw[gsn'`dxxRglabjf+wgjW`doiuQlotlw[5413`dxxRlzi.kmwqYnkhici"|nm^km``~XkfexR?=6:kmwqYe}`%bb~zPibc`l`)uidUbbikw_bmvjqY5:j1bb~zPbtk,mkusW`ijoek r`o\mkbbpVidyczPnnv34575l2ceyQmuh-jjvrXajkhdh!}al]jjacWje~byQaou234476n2ceyQmuh-jjvrXajkhdh!|_GQN[C@c98l0ec}{_cwj+lht|Vchmnfj/r]EWHYANm89>6gasu]aql)nfz~Tenolhd-p[CUJWOLo> Ga229jjvrXj|c$ec}{_habgmc({VLXARHId3/Jj47a3`dxxRlzi.kmwqYnkhici"}PFRO\BCb4::1bb~zPbtk,mkusW`ijoek s^DPIZ@Al:'Bb<<9;hlppZdra&ceyQfc`aka*uXNZGTJKj<-Hl\WR66n2ceyQmuh-jjvrXajkhdh!|_GQN[C@c<;80ec}{_cwj+lht|Vchmnfj/r]EWHYANm>&Ec<<;hlppZdra&ceyQfc`aka*uXNZGTJKj;-Hl25c=nfz~Tnxg ioqw[lefkao$RH\M^DE`07a3`dxxRlzi.kmwqYnkhici"}PFRO\BCb1:;1bb~zPbtk,mkusW`ijoek s^DPIZ@Al?'Bb?=4ioqw[gsn'`dxxRglabjf+vYA[DUMJi8"Io32b>oi{}Uiyd!fnrv\mfgd`l%xSK]B_GDg34`582ceyQmuh-jjvrXajkhdh!|_GQN[Jss088:7d`|t^`vm*oi{}Ubolmge.q\ghvXmx:;<=<<;hlppZdra&ceyQfc`aka*uXkdzTi|>?013461=nfz~Tnxg ioqw[lefkao$Rmbp^gr45679>;9:6gasu]aql)nfz~Tenolhd-p[fkwWl{;<=>>7^d666=nfz~Tnxg ioqw[lefkao$Rmbp^gr4567;;887d`|t^`vm*oi{}Ubolmge.q\ghvXmx:;<==<209jjvrXj|c$ec}{_habgmc({Vif|Rk~012267=nfz~Tnxg ioqw[lefkao$Rmbp^gr45669;;0ec}{_cwj+lht|Vchmnfj/r]`iuYby9:;>?<4ioqw[gsn'`dxxRglabjf+vYdeyUn}=>?2006?lht|Vh~e"gasu]jgdeom&~jkRgaddz\v`a;878=7d`|t^`vm*oi{}Ubolmge.vbcZoillrT~hi311<12>oi{}Uiyd!fnrv\mfgd`l%mjQfneg{[wc`48;5>;5fnrv\fpo(agySdmncig,pdaXagnntR|jg=31:702ceyQmuh-jjvrXajkhdh!{af]jjacW{ol0<;1279jjvrXj|c$ec}{_habgmc(|hmTecjjx^pfc9716;<0ec}{_cwj+lht|Vchmnfj/ucd[lhcmqUyij2>7?06?lht|Vh~e"gasu]jgdeom&~jkRgaddz\v`a;978>7d`|t^`vm*oi{}Ubolmge.vbcZoillrT~hi32?06?lht|Vh~e"gasu]jgdeom&~jkRgaddz\v`a;;78>7d`|t^`vm*oi{}Ubolmge.vbcZoillrT~hi34?06?lht|Vh~e"gasu]jgdeom&~jkRgaddz\v`a;=78>7d`|t^`vm*oi{}Ubolmge.vbcZoillrT~hi36?06?lht|Vh~e"gasu]jgdeom&~jkRgaddz\v`a;?78>7d`|t^`vm*oi{}Ubolmge.vbcZoillrT~hi38?06?lht|Vh~e"gasu]jgdeom&~jkRgaddz\v`a;178?7d`|t^`vm*oi{}Ubolmge.vbcZoillrT~hiP0368mkusWkb#d`|t^k`efnb'}klSd`key]qabY6:<1bb~zPbtk,mkusW`ijoek t`e\mkbbpVxnkR??249jjvrXj|c$ec}{_habgmc(|hmTecjjx^pfcZ76:<1bb~zPbtk,mkusW`ijoek t`e\mkbbpVxnkR?=249jjvrXj|c$ec}{_habgmc(|hmTecjjx^pfcZ74:<1bb~zPbtk,mkusW`ijoek t`e\mkbbpVxnkR?;249jjvrXj|c$ec}{_habgmc(|hmTecjjx^pfcZ72:<1bb~zPbtk,mkusW`ijoek t`e\mkbbpVxnkR?9249jjvrXj|c$ec}{_habgmc(|hmTecjjx^pfcZ70:=1bb~zPbtk,mkusW`ijoek t`e\mkbbpVxnkR<=4:kmwqYe}`%bb~zPibc`l`)sinUbbikw_sgd[6433`dxxRlzi.kmwqYnkhici"zng^km``~XzlmT8?:4ioqw[gsn'`dxxRglabjf+qg`W`doiuQ}ef]661=nfz~Tnxg ioqw[lefkao$xliPioff|ZtboV<986gasu]aql)nfz~Tenolhd-webYnfmosSkh_607?lht|Vh~e"gasu]jgdeom&~jkRgaddz\v`aX0;>0ec}{_cwj+lht|Vchmnfj/ucd[lhcmqUyijQ6269jjvrXj|c$ec}{_habgmc(|hmT~lcPaefq[rt;87837d`|t^`vm*oi{}Ubolmge.vbcZtfeVkohQxr=2=5713?=7:kmwqYe}`%bb~zPibc`l`)sinUym`Qndep\sw:46;20ec}{_cwj+lht|Vchmnfj/ucd[wgjWhno~Ry}<2<262=nfz~Tnxg ioqw[lefkao$xliPr`o\eabuW~x783<7;hlppZdra&ceyQfc`aka*rfoVxjaRokds]tv9299;=0ec}{_cwj+lht|Vchmnfj/ucd[wgjWhno~Ry}<4<1<>oi{}Uiyd!fnrv\mfgd`l%mjQ}al]b`atX{6>2<<8;hlppZdra&ceyQfc`aka*rfoVxjaRokds]tv909:11bb~zPbtk,mkusW`ijoek t`e\vdkXimnySz|36?313>oi{}Uiyd!fnrv\mfgd`l%mjQ}al]b`atX{6<2?64ioqw[gsn'`dxxRglabjf+qg`W{kfSljkr^uq8286:>1bb~zPbtk,mkusW`ijoek t`e\vdkXimnySz|38?0;?lht|Vh~e"gasu]jgdeom&~jkR|nm^cg`wYpz525=?94ioqw[gsn'`dxxRglabjf+qg`W{kfSio{a^pg858502ceyQmuh-jjvrXajkhdh!{af]qehYci}kT~i2>0?0;?lht|Vh~e"gasu]jgdeom&~jkR|nm^fbpdYul5;:2?64ioqw[gsn'`dxxRglabjf+qg`W{kfSio{a^pg8449:11bb~zPbtk,mkusW`ijoek t`e\vdkXlh~jSj312<1<>oi{}Uiyd!fnrv\mfgd`l%mjQ}al]geqgXzm6:83<7;hlppZdra&ceyQfc`aka*rfoVxjaRjnt`]q`9726;20ec}{_cwj+lht|Vchmnfj/ucd[wgjWmkmR|k<04=6==nfz~Tnxg ioqw[lefkao$xliPr`o\`drfW{n7=:0=8:kmwqYe}`%bb~zPibc`l`)sinUym`Qkauc\va:607837d`|t^`vm*oi{}Ubolmge.vbcZtfeVnjxlQ}d=3::7>1299jjvrXj|c$ec}{_habgmc(|hmT~lcPd`vb[wb;:849;6gasu]aql)nfz~Tenolhd-webYuidUomyoPre>7:71oi{}Uiyd!fnrv\mfgd`l%mjQ}al]geqgXzm632?94ioqw[gsn'`dxxRglabjf+qg`W{kfSio{a^pg8<85>2ceyQmuh-jjvrXajkhdh!xosf\mkbbpVxnk1>1279jjvrXj|c$ec}{_habgmc(fxoSd`key]qab:66;<0ec}{_cwj+lht|Vchmnfj/vmq`ZoillrT~hi32?06?lht|Vh~e"gasu]jgdeom&}d~iQfneg{[wc`W98>7d`|t^`vm*oi{}Ubolmge.ulvaYnfmosSkh_006?lht|Vh~e"gasu]jgdeom&}d~iQfneg{[wc`W;8i7d`|t^`vm*oi{}Ubolmge.ulvaYnfmosSkh_omw4566:j1bb~zPbtk,mkusW`ijoek wnpg[lhcmqUyijQaou234474:2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-NvdkXZHG:?>5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(E{kfS_OB1110?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"C}al]QEH76;:1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,IwgjW[KF=?=<;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&Gym`Q]AL3076=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| Mscn[WGJ9=987d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*KuidUYM@?:329jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$Aob_SCN53543`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.OqehYUID;5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(E{kfS_OB1910?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"C}al]QEH7>;;1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,IwgjW[KF>>=4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'DxjaR\NM3207>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!Br`o\VDK59:90ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+HtfeVXJA?<<3:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O17658?6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)JzhgT^LC=5218mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#@|nm^PBI704;2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-NvdkXZHG9;>=4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'DxjaR\NM3:07>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!Br`o\VDK51:80ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+HtfeVXJA>=<;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&Gym`Q]AL1376=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| Mscn[WGJ;8987d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*KuidUYM@==329jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$Aob_SCN76543`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.OqehYUID9??>5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(E{kfS_OB3410?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"C}al]QEH51;:1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,IwgjW[KF?:=<;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&Gym`Q]AL1;76=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| Mscn[WGJ;0997d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*KuidUYM@:<3:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O7465=4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'DxjaR\NM5707>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!Br`o\VDK3>:90ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+HtfeVXJA99<3:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O7<656gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)JzhgT^LC:329jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$Aob_SCN15543`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.OqehYUID?:?>5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(E{kfS_OB5310?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"C}al]QEH34;:1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,IwgjW[KF99=<;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&Gym`Q]AL7676=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| Mscn[WGJ=?987d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*KuidUYM@;8329jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$Aob_SCN1=543`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.OqehYUID?2??5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(E{kfS_OB6218mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#@|nm^PBI364;2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-NvdkXZHG==>=4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'DxjaR\NM7007>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!Br`o\VDK1;:90ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+HtfeVXJA;:<3:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%F~lcPR@O51654:2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-NvdkXZHG3`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.]uewoillr;<=>30?1b?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"Qyaskm``~789:7==0?01>27;5f3`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.]uewoillr;<=>315<0e>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!Pv`pjjac89:;0<;13`9jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$S{o}ioff|56785;=2>o4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:6?79j7d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?5=84i2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-\rdtnfmos<=>?<0;=7<=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| _wcqmkbbp9:;<1?13`9jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$S{o}ioff|567858;2>o4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:5979j7d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?6784i2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-\rdtnfmos<=>?<31=7d=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| _wcqmkbbp9:;<1<;>2c8mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}67896993=n;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&U}mgaddz3456;:?48m6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)X~hxbbikw01238719;h1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,[sguagnnt=>?0=0;:6g3=n;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&U}mgaddz3456;;948m6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)X~hxbbikw01238679;h1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,[sguagnnt=>?0=11:6g?01>03;5f3`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.]uewoillr;<=>339<0e>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!Pv`pjjac89:;0>71389jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$S{o}ioff|5678595?l5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(Wkyecjjx12349276:k0ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+Zpfz`doiu>?01>75;5f3`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.]uewoillr;<=>343<0e>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!Pv`pjjac89:;09=13`9jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$S{o}ioff|56785>?2>o4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'V|j~d`key2345:3=79j7d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?0384i2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-\rdtnfmos<=>?<55=7d=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| _wcqmkbbp9:;<1:7>2c8mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}67896?53=6;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&U}mgaddz3456;<79j7d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*Yqi{cehhv?012?1584i2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-\rdtnfmos<=>?<43=7d=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| _wcqmkbbp9:;<1;=>2c8mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#Rxnrhlga}67896>?3=n;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&U}mgaddz3456;==48m6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)X~hxbbikw01238039;h1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,[sguagnnt=>?0=75:6gw0p,[sguagnnt=>?0=43:6g?01>51;5f3`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.]uewoillr;<=>367<0e>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!Pv`pjjac89:;0;91389jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$S{o}ioff|56785<5?45fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(Wkyecjjx1234919;01bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,[sguagnnt=>?0=:=7<=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| _wcqmkbbp9:;<171339jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c>3:65>218mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#iazt^`?5784;2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-gkprXj5;82>=4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'me~xRl315<07>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!kotv\f9726:90ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+air|Vh7=;0<3:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb=34:65208mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#iazt^`?5;543`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYe4;:5?>5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(lfSo2=1?10?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a8749;:1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,`jssWk69?3=<;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&ndyyQm<36=76=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| dnww[g:5=7987d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*bh}}Ui0?81329jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c>13;543`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYe4;25?>5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(lfSo2=9?11?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a8784;2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-gkprXj59;2>=4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'me~xRl330<07>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!kotv\f9556:90ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+air|Vh7?>0<3:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb=17:65218mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#iazt^`?7284;2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-gkprXj5932>=4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'me~xRl338<06>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!kotv\f959;:1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,`jssWk6?<3=<;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&ndyyQm<53=76=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| dnww[g:3:7987d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*bh}}Ui09=1329jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c>70;543`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYe4=?5?>5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(lfSo2;6?10?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a8119;:1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,`jssWk6?43=<;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&ndyyQm<5;=77=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| dnww[g:36:90ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+air|Vh79=0<3:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb=72:65218mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#iazt^`?1184;2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-gkprXj5?>2>=4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'me~xRl357<07>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!kotv\f9306:90ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+air|Vh7950<3:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb=7::641329jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c>55;543`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYe4?85?>5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(lfSo293?10?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a8329;:1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,`jssWk6=93=<;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&ndyyQm<74=76=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| dnww[g:1?7997d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*bh}}Ui0;0<2:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb=5=77=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| dnww[g:?6:80ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+air|Vh753=>;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&ndyyQm_112?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a[4553`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYeW8:8>6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)cg|~TnR?>339jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c]2664:80ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+air|VhT=:==;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&ndyyQm_0:06>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!kotv\fZ7>;81bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,`jssWkU9??5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(lfSoQ=0208mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#iazt^`\64553`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYeW;88>6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)cg|~TnR<<339jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c]10644=>;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&ndyyQm_211?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a[664:2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-gkprXjV9:??5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(lfSoQ<2208mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#iazt^`\76553`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYeW:>8>6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)cg|~TnR=:339jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c]0264997d`|t^`vm*oi{}U|~dzj_gkek*oi{}Uo|ob_0u2v*bh}}UiS>6<2:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPdqpbiZ7p9{%ocxzPb^1:74=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| dnww[gY3;;1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,`jssWkU?<><4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'me~xRlP4011?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a[144:2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-gkprXjV>8??5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(lfSoQ;4208mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#iazt^`\00553`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYeW=<8>6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)cg|~TnR:8339jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c]7<64oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!kotv\fZ36;;1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,`jssWkU>>><4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'me~xRlP5211?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a[024:2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-gkprXjV?>??5fnrv\fpo(agySz|ftd]emci(agySi~}al]2s4t(lfSoQ:6208mkusWkb#d`|t^uqmqcXn`ld#d`|t^fsvdkX9~;y#iazt^`\12553`dxxRlzi.kmwqYpz`~nSkgio.kmwqYcx{kfSr.flqqYeW<28>6gasu]aql)nfz~T{g{e^djbj)nfz~Th}|nm^3t5w)cg|~TnR;6309jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_erqehY68x$hb{{_c]577=nfz~Tnxg ioqw[rtn|lUmeka ioqw[avuidU:{<| dnww[gY18:80ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+air|VhT:<==;hlppZdra&ceyQxrhvf[coag&ceyQkpscn[4q6z&ndyyQm_7006>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\`utfeV;|=!kotv\fZ04;;1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,`jssWkU=8><4ioqw[gsn'`dxxRy}iug\bl`h'`dxxRjr`o\5r7u'me~xRlP6411?lht|Vh~e"gasu]tvlrbWocmc"gasu]gtwgjW8}:~"j`uu]a[304:2ceyQmuh-jjvrX{ciRhffn-jjvrXlyxjaR?x1s-gkprXjV<:l1bb~zPbtk,mkusW~xbxhQiigm,mkusWmzym`Q>w0p,s`Yf9;l0ec}{_cwj+lht|V}yeykPfhdl+lht|Vn{~lcP1v3q+rcXiV:?m6gasu]aql)nfz~T{g{e^djbj)nfz~Tt`l_gkekZesze%FmijPpV]ma}rXimnxyo>?01]`}979Pcx>2:474:2ceyQmuh-jjvrX{ciRhffn-jjvrX{pdhSkgio^awvi)bey~r?l5fnrv\fpo(agySz|ftd]emci(agyS~wac^djbjYd|{f$jdh`_qpf[cskd:;0ec}{_cwj+lht|V}yeykPfhdl+lht|VyrbnQiigm\gqtk'og`><4ioqw[gsn'`dxxRy}iug\bl`h'`dxxR}vnb]emciXk}xg#}\30?11?lht|Vh~e"gasu]tvlrbWocmc"gasu]p}keXn`ldSnz}l.rQ8484:2ceyQmuh-jjvrX{ciRhffn-jjvrX{pdhSkgio^awvi)wZ585??5fnrv\fpo(agySz|ftd]emci(agyS~wac^djbjYd|{f$|_2<>238mkusWkb#d`|t^uqmqcXn`ld#d`|t^qzjfYaaoeToy|c/qP\467>?4ioqw[gsn'`dxxRy}iug\bl`h'`dxxR}vnb]emciXk}xg#}\P32:8mkusWkb#d`|t^uqmqcXn`ld#d`|t^qzjfYaaoeToy|c/qP\j`~s494:?55fnrv\fpo(agySz|ftd]emci(agyS~wac^djbjYd|{f$|_Qaeyv?5;7402ceyQmuh-jjvrX{ciRhffn-jjvrX{pdhSkgio^awvi)wZVdnty2=>01;?lht|Vh~e"gasu]tvlrbWocmc"gasu]p}keXn`ldSnz}l.rQ[kc|595=>74ioqw[gsn'`dxxRy}iug\bl`h'`dxxR}vnb]emciXk}xg#}\Pndzw86869:h0ec}{_cwj+lht|V}yeykPfhdl+lht|VyrbnQiigm\gqtk'yXTbhv{<2<2[c34:2ceyQmuh-jjvrX{ciRhffn-jjvrX{pdhSkgio^awvi)w_5:5??5fnrv\fpo(agySz|ftd]emci(agyS~wac^djbjYd|{f$|Z2>>208mkusWkb#d`|t^uqmqcXn`ld#d`|t^qzjfYaaoeToy|c/qU?6;553`dxxRlzi.kmwqYpz`~nSkgio.kmwqYtqgiTjdh`_bvqh*vP4:48=6gasu]aql)nfz~T{g{e^djbj)nfz~Tt`l_gkekZesze%{[R><1:kmwqYe}`%bb~zPwskwaZ`nnf%bb~zPsxl`[coagVi~a!W^305>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\w|hdWocmcRm{rm-sSZ4492ceyQmuh-jjvrX{ciRhffn-jjvrX{pdhSkgio^awvi)w_V98;6gasu]aql)nfz~T{g{e^djbj)nfz~Tt`l_gkekZesze%{[R`jxu>3:6>369jjvrXj|c$ec}{_vpjp`Yaaoe$ec}{_r{mgZ`nnfUhxb pV]ma}r;97937d`|t^`vm*oi{}U|~dzj_gkek*oi{}UxucmPfhdl[frud&z\Sckwt=3=561?2763?lht|Vh~e"gasu]tvlrbWocmc"gasu]p}keXn`ldSnz}l.rqaZcjx}sTmcj?0126016:7d`|t^`vm*oi{}U|~dzj_gkek*oi{}UxucmPfhdl[frud&zyiRhzlm]bja6789?:SK:>;hlppZdra&ceyQxrhvf[coag&ceyQ|yoa\bl`hWj~y`"~}e^dvhiYffm:;<=;>_F1e?lht|Vh~e"gasu]tvlrbWocmc"gasu]p}keXn`ldSnz}l.rqaZ`rdeUjbi>?014606=nfz~Tnxg ioqw[rtn|lUmeka ioqw[vikVlbjbQltsn,twcXn|fgSl`k012320YT_99:7d`|t^`vm*oi{}U|~dzj_gkek*oi{}UxucmPfhdl[frud&xnmi==;hlppZdra&ceyQxrhvf[coag&ceyQ|yoa\bl`hWj~y`"|jae302>oi{}Uiyd!fnrv\swosmVlbjb!fnrv\w|hdWocmcRm{rm-tevYpz`~n?h5fnrv\fpo(agySz|ftd]emci(agyS~wac^djbjYd|{f${l}PwskwaZhh|9:;=>h4ioqw[gsn'`dxxRy}iug\bl`h'`dxxR}vnb]emciXk}xg#zo|_vpjp`Yig}:;<oi{}Uiyd!fnrv\swosmVlbjb!ts]q848592ceyQmuh-jjvrX{ciRhffn-spwYu4;49=6gasu]aql)nfz~T{g{e^djbj)w|{Uy0>0>3:kmwqYe}`%yiljPcxaoa4g?013a?lht|Vh~e"|jae]`}fjbWfx;<=>>1c9jjvrXj|c$~hok_b{`h`Yhz9:;oi{}Uiyd!|_GQN[C@c:820ec}{_cwj+vYA[DUMJi<"Io055d=nfz~Tnxg s^DPIZ@Al;'Bb?8PF0c8mkusWkb#~QISL]EBa4*Ag8=SJ?7;hlppZdra&yTJ^CPFGf1)Lh28820ec}{_cwj+vYA[DUMJi<"Io775==nfz~Tnxg s^DPIZ@Al;'Bb:?>3:kmwqYe}`%xSK]B_GDg7401bb~zPbtk,wZ@TEVLMh>#Fn334?lht|Vh~e"}PFRO\BCb4%@d8=45fnrv\fpo({VLXARHId2/JjZ`2901bb~zPbtk,wZ@TEVLMh>#Fn^d551=nfz~Tnxg s^DPIZIr|9;:86gasu]aql)tWOYFSB{{3037?lht|Vh~e"}PFRO\Kpr398>0ec}{_cwj+vYA[DUDyy;>199jjvrXj|c$ycmncigg[dedmzy:j6gasu]aql)rfjkhdhjPabafwvYhz9:;4ioqw[gsn'|dhmnfjd^c`g`utWfx;<=>>229jjvrXx`zn`d`j/DZ\asci|zUj`xQnlt]lrc403`dxxR~fpdnjj`)BPVo}icz|_`nv[djrWf|mS^Y?229jjvrXx`zn`d`j/DZ\asci|zUj`xQnlt]vrc403`dxxR~fpdnjj`)BPVo}icz|_`nv[djrW||mS^Y?289jjvrXx`zn`d`j/DZ\asci|zUfi` kauc\hjgcWlxy>l5fnrv\tlvbd`dn#HVPewgmpvYjmd$omyoPsumqaZcuz:;0ec}{_qksaioim&OSShxjnuq\i`kXlh~jSaand^gqvZkrp9:;9>;4ioqw[uowmecei"KW_dtfjquXelgThlzn_mmb`ZcuzVg~t=>?5^QT464oi{}U{e}kciog,A]Yb~ldRcjm^fbpdYt|fxnSh|}_np3456Xag|8:6gasu]smuckago$IUQjvdlwwZkbeVnjxlQ|tnpf[`tuWfx;<=>Piot25f=nfz~T|d~jlhlf+@^X{}kli#G]_032g>oi{}U{e}kciog,A]Yt|hmn"D\P133`?lht|Vzb|hbfnd-F\Zusino%E_Q>30a8mkusWyc{iagae.G[[vrfol$B^R?;1b9jjvrXx`zn`d`j/DZ\wqg`m'CYS<;>c:kmwqYwayogeck EY]ppdab&@XT=;?l;hlppZvnxlfbbh!JX^qwebc)A[U:;8i0ec}{_qksaioim&OSS~zngd,JVZ409j1bb~zPphrfhlhb'LRTyohe/KQ[7>6k2ceyQiqgomkc(MQUxxlij.HP\6<7d3`dxxR~fpdnjj`)BPVymjk!IS]044e;hlppZvnxlfbbh!JX^qwebc)ieTc};hlppZvnxlfbbh!JX^qwebc)ieTc}8:7d`|t^rjt`jnfl%NTR}{afg-eisXgy8T=5<>;hlppZvnxlfbbh!JX^qwebc)ieTc}4ioqw[uowmecei"KW_rvbc`(fd|Ud|?Q<209jjvrXx`zn`d`j/DZ\wqg`m'kgyRa2^1364=nfz~T|d~jlhlf+@^X{}kli#ocu^ms6Z56:91bb~zPphrfhlhb'LRTyohe/coqZiw:V>9<6gasu]smuckago$IUQ|t`ef*djrWfz9S8582ceyQiqgomkc(MQUxxlij.`nv[jv5W08=7d`|t^rjt`jnfl%NTR}{afg-gqtk&hfbkcQcegv17>oi{}U{e}kciog,A]Yt|hmn"nz}l/coq+gcl;?0ec}{_qksaioim&OSS~zngd,`pwj)ie%mijP1378mkusWyc{iagae.G[[vrfol$hxb!amw-eabX:;20ec}{_qksaioim&OSS~zngd,`pwj)ie%cxz|em]36==nfz~T|d~jlhlf+@^X{}kli#m{rm,bhp(h}}yn`R?=8:kmwqYwayogeck EY]ppdab&j~y`#ocu/mvpvckW;8=7d`|t^rjt`jnfl%NTR}{afg-gqtk&hf~Shvl_dl16>oi{}U{e}kciog,A]Yt|hmn"nz}l/``[kis:=1bb~zPphrfhlhb'LRTyohe/awvi(ekVyyoR>=4:kmwqYwayogeck EY]ppdab&j~y`#ll_rp`[4453`dxxR~fpdnjj`)BPVymjk!cupo*gtffjb9;6gasu]smuckago$IUQ|t`ef*frud'hrxhQjn^`zt75oi{}U{e}kciog,A]Yt|hmn"nz}l/g{gZu~{jkg`?>4ioqw[uowmecei"KW_rvbc`(d|{f%fxc249jjvrXx`zn`d`j/DZ\wqg`m'i~a eulr\hjh`:>1bb~zPphrfhlhb'LRTyohe/awvi(kghnTdiaee05?lht|Vzb|hbfnd-F\Zusino%oy|c.lwo[dedmzy946gasu]smuckago$IUQ|t`ef*frud'g~`Rffln]pai403`dxxR~fpdnjj`)BPVymjk!cupo*hskWacgcRyj299jjvrXx`zn`d`j/DZ\wqg`m'i~a bum]nqiYcad986gasu]smuckago$IUQ|t`ef*frud'g~`R}Puo06?lht|Vzb|hbfnd-F\Zusino%oy|c.lwo[vrfz}8?7d`|t^rjt`jnfl%NTR}{afg-gqtk&{olSagak378mkusWyc{iagae.G[[vrfol$hxb!sikepZd~x;k0ec}{_qksaioim&OSS~zngd,`pwj){acmxRaifrgw[54?3`dxxR~fpdnjj`)BPVymjk!cupo*vo`fVosxRlvp368mkusWyc{iagae.G[[vrfol$hxb!wnpg6Zci:=1bb~zPphrfhlhb'LRTyohe/awvi(pg{n?Sh`=9:kmwqYwayogeck EY]ppdab&j~y`#yts]pvfubdV::o6gasu]smuckago$IUQ|t`ef*`vdW9;h7d`|t^rjt`jnfl%NTR}{afg-aueX98n0ec}{_qksaioim&OSS~zngd,ftfY688n0ec}{_qksaioim&OSS~zngd,ftfY698n0ec}{_qksaioim&OSS~zngd,ftfY6:8n0ec}{_qksaioim&OSS~zngd,ftfY6;8n0ec}{_qksaioim&OSS~zngd,ftfY6<8n0ec}{_qksaioim&OSS~zngd,ftfY6=8n0ec}{_qksaioim&OSS~zngd,ftfY6>8n0ec}{_qksaioim&OSS~zngd,ftfY6?8n0ec}{_qksaioim&OSS~zngd,ftfY608n0ec}{_qksaioim&OSS~zngd,ftfY618i0ec}{_qksaioim&OSS~zngd,ftfY59m1bb~zPphrfhlhb'LRTyohe/gsgZ479m1bb~zPphrfhlhb'LRTyohe/gsgZ469m1bb~zPphrfhlhb'LRTyohe/gsgZ459m1bb~zPphrfhlhb'LRTyohe/gsgZ449m1bb~zPphrfhlhb'LRTyohe/gsgZ439m1bb~zPphrfhlhb'LRTyohe/gsgZ429m1bb~zPphrfhlhb'LRTyohe/gsgZ419m1bb~zPphrfhlhb'LRTyohe/gsgZ409m1bb~zPphrfhlhb'LRTyohe/gsgZ4?9m1bb~zPphrfhlhb'LRTyohe/gsgZ4>9j1bb~zPphrfhlhb'LRTyohe/gsgZ56l2ceyQiqgomkc(MQUxxlij.dr`[666l2ceyQiqgomkc(MQUxxlij.dr`[676k2ceyQiqgomkc(MQUxxlij.dr`[17d3`dxxR~fpdnjj`)BPVymjk!eqa\14eoi{}U{e}kciog,A]Yt|hmn"h~l_93`?lht|Vzb|hbfnd-F\Zusino%i}mP93g8mkusWyc{iagae.G[[vrfol$nzh`{s^km*lht|VfdmiQjrs0e?lht|Vzb|hbfnd-F\Zusino%i{katr]jj+oi{}U{~dxPaefq5d=nfz~T|d~jlhlf+@^X{}kli#``p0d8mkusWyc{iagae.G[[vrfol${mRaif^22b>oi{}U{e}kciog,A]Yt|hmn"}oPogd\54eoi{}U{e}kciog,A]Yt|hmn"}ma_022`>oi{}U{e}kciog,A]Yt|hmn"}ma_032`>oi{}U{e}kciog,A]Yt|hmn"}ma_002`>oi{}U{e}kciog,A]Yt|hmn"}ma_012`>oi{}U{e}kciog,A]Yt|hmn"}ma_062`>oi{}U{e}kciog,A]Yt|hmn"}ma_072`>oi{}U{e}kciog,A]Yt|hmn"}ma_042`>oi{}U{e}kciog,A]Yt|hmn"}ma_052`>oi{}U{e}kciog,A]Yt|hmn"}ma_0:2`>oi{}U{e}kciog,A]Yt|hmn"}ma_0;2g>oi{}U{e}kciog,A]Yt|hmn"}ma_33g?lht|Vzb|hbfnd-F\Zusino%|n`P213g?lht|Vzb|hbfnd-F\Zusino%|n`P203g?lht|Vzb|hbfnd-F\Zusino%|n`P233g?lht|Vzb|hbfnd-F\Zusino%|n`P223g?lht|Vzb|hbfnd-F\Zusino%|n`P253g?lht|Vzb|hbfnd-F\Zusino%|n`P243g?lht|Vzb|hbfnd-F\Zusino%|n`P273g?lht|Vzb|hbfnd-F\Zusino%|n`P263g?lht|Vzb|hbfnd-F\Zusino%|n`P293g?lht|Vzb|hbfnd-F\Zusino%|n`P283`?lht|Vzb|hbfnd-F\Zusino%|n`P30f8mkusWyc{iagae.G[[vrfol${ocQ<00f8mkusWyc{iagae.G[[vrfol${ocQ<10a8mkusWyc{iagae.G[[vrfol${ocQ;1b9jjvrXx`zn`d`j/DZ\wqg`m'zhbR;>c:kmwqYwayogeck EY]ppdab&yieS;?l;hlppZvnxlfbbh!JX^qwebc)xjdT;>f:kmwqYwayogeck EY]ppdab&{olSlQ>10d8mkusWyc{iagae.G[[vrfol$yijQn_002b>oi{}U{e}kciog,A]Yt|hmn"kh_`]274`f:kmwqYwayogeck EY]ppdab&{olSlQ>90g8mkusWyc{iagae.G[[vrfol$yijQn_33e?lht|Vzb|hbfnd-F\Zusino%~hiPa^035c=nfz~T|d~jlhlf+@^X{}kli#|jg^c\647a3`dxxR~fpdnjj`)BPVymjk!rde\eZ459o1bb~zPphrfhlhb'LRTyohe/pfcZgX::;m7d`|t^rjt`jnfl%NTR}{afg-v`aXiV8?=k5fnrv\tlvbd`dn#HVPsucda+tboVkT>8?i;hlppZvnxlfbbh!JX^qwebc)zlmTmR<91g9jjvrXx`zn`d`j/DZ\wqg`m'xnkRoP263e?lht|Vzb|hbfnd-F\Zusino%~hiPa^0;5c=nfz~T|d~jlhlf+@^X{}kli#|jg^c\6<7b3`dxxR~fpdnjj`)BPVymjk!rde\eZ56n2ceyQiqgomkc(MQUxxlij.sgd[dY488l0ec}{_qksaioim&OSS~zngd,qabYfW:;:i6gasu]smuckago$IUQ|t`ef*wc`WhU?=h5fnrv\tlvbd`dn#HVPsucda+tboVkT9e:kmwqYwayogeck EY]ppdab&{olSlQ71d9jjvrXx`zn`d`j/DZ\wqg`m'xnkRoP90g8mkusWyc{iagae.G[[vrfol$yijQm_13f?lht|Vzb|hbfnd-F\Zusino%~hiPb^32b>oi{}U{e}kciog,A]Yt|hmn"kh_c]244`f:kmwqYwayogeck EY]ppdab&{olSoQ>60d8mkusWyc{iagae.G[[vrfol$yijQm_052b>oi{}U{e}kciog,A]Yt|hmn"kh_c]2<4`??i;hlppZvnxlfbbh!JX^qwebc)zlmTnR<<1g9jjvrXx`zn`d`j/DZ\wqg`m'xnkRlP253e?lht|Vzb|hbfnd-F\Zusino%~hiPb^065c=nfz~T|d~jlhlf+@^X{}kli#|jg^`\637a3`dxxR~fpdnjj`)BPVymjk!rde\fZ409o1bb~zPphrfhlhb'LRTyohe/pfcZdX:1;m7d`|t^rjt`jnfl%NTR}{afg-v`aXjV82=h5fnrv\tlvbd`dn#HVPsucda+tboVhT?>>f:kmwqYwayogeck EY]ppdab&{olSoQ<1338mkusWyc{iagae.G[[vrfol$yijQm_23\54c2g9jjvrXx`zn`d`j/DZ\wqg`m'ycekzPcupo*vnfe}Ue~`Q?_30g?lht|Vzb|hbfnd-F\Zusino%egit^awvi(t`hgSc|b_00g?lht|Vzb|hbfnd-F\Zusino%egit^awvi(t`hgSc|b_30g?lht|Vzb|hbfnd-F\Zusino%egit^awvi(t`hgSc|b_20g?lht|Vzb|hbfnd-F\Zusino%egit^awvi(t`hgSc|b_50g?lht|Vzb|hbfnd-F\Zusino%egit^awvi(t`hgS`k_00e?lht|Vzb|hbfnd-F\Zusino%egit^awvi(t`hgS`k_0]26c=nfz~T|d~jlhlf+@^X{}kli#}gigv\gqtk&zbjayQ}ne]2[74a3`dxxR~fpdnjj`)BPVymjk!sikepZesze$xdlc{_slg[4Y4:m1bb~zPphrfhlhb'LRTyohe/qkmcrXk}xg"~fnmu]qjaY5:m1bb~zPphrfhlhb'LRTyohe/qkmcrXk}xg"~fnmu]qjaY4:m1bb~zPphrfhlhb'LRTyohe/qkmcrXk}xg"~fnmu]qjaY3:m1bb~zPphrfhlhb'LRTyohe/qkmcrXk}xg"~fffu]bvlro:m1bb~zPphrfhlhb'LRTyohe/qkmcrXk}xg"~fffu]qmbns9k1bb~zPphrfhlhb'LRTyohe/tb[57e3`dxxR~fpdnjj`)BPVymjk!v`]25f=nfz~T|d~jlhlf+@^X{}kli#xn_022g>oi{}U{e}kciog,A]Yt|hmn"{oP103`?lht|Vzb|hbfnd-F\Zusino%zlQ>20a8mkusWyc{iagae.G[[vrfol$}mR?<1b9jjvrXx`zn`d`j/DZ\wqg`m'|jS<:>c:kmwqYwayogeck EY]ppdab&kT=8?l;hlppZvnxlfbbh!JX^qwebc)~hU::oi{}U{e}kciog,A]Yt|hmn"{oP243`?lht|Vzb|hbfnd-F\Zusino%zlQ=60a8mkusWyc{iagae.G[[vrfol$}mR<81b9jjvrXx`zn`d`j/DZ\wqg`m'|jS?6>c:kmwqYwayogeck EY]ppdab&kT>4?m;hlppZvnxlfbbh!JX^qwebc)~hU8=n5fnrv\tlvbd`dn#HVPsucda+pfW:::o6gasu]smuckago$IUQ|t`ef*sgX;8;i7d`|t^rjt`jnfl%NTR}{afg-rdY39k1bb~zPphrfhlhb'LRTyohe/tb[07e3`dxxR~fpdnjj`)BPVymjk!v`]55g=nfz~T|d~jlhlf+@^X{}kli#xn_63a?lht|Vzb|hbfnd-F\Zusino%zlQ71c9jjvrXx`zn`d`j/DZ\wqg`m'|jS4<;;hlppZvnxlfbbh!JX^qwebcXA[Ufyu>?00>3:73?1=32:70?00>26;413`dxxR~fpdnjj`)BPVymjkPIS]nq}67886:>3?=5:kmwqYwayogeck EY]ppdabW@XTaxv?013?5685>2ceyQiqgomkc(MQUxxlij_HP\ip~789;7=>0>249jjvrXx`zn`d`j/DZ\wqg`mVCYS`{w01228429:?1bb~zPphrfhlhb'LRTyohe^KQ[hs89::0<:11378mkusWyc{iagae.G[[vrfolUB^Rczx12359726;<0ec}{_qksaioim&OSS~zngd]JVZkrp9:;=1?:>006?lht|Vzb|hbfnd-F\ZusinoTE_Qbuy2344:6>78=7d`|t^rjt`jnfl%NTR}{afg\MWYj}q:;<<2>6?311>oi{}U{e}kciog,A]Yt|hmnSD\Pmtz3457;9>49:6gasu]smuckago$IUQ|t`ef[LTXe|r;<=?316<260=nfz~T|d~jlhlf+@^X{}kliRG]_lw{45664825>;5fnrv\tlvbd`dn#HVPsucdaZOUWds<=>><0:=573?1=3::4433`dxxR~fpdnjj`)BPVymjkPIS]nq}67886:2?;4ioqw[uowmecei"KW_rvbc`YNZVg~t=>?1=3=573?1=03:4433`dxxR~fpdnjj`)BPVymjkPIS]nq}6788692?;4ioqw[uowmecei"KW_rvbc`YNZVg~t=>?1=0=57285fnrv\tlvbd`dn#HVPsucdaZOUWds<=>><2<261=nfz~T|d~jlhlf+@^X{}kliRG]_lw{45664=4996gasu]smuckago$IUQ|t`ef[LTXe|r;<=?34?310>oi{}U{e}kciog,A]Yt|hmnSD\Pmtz3457;=78>7d`|t^rjt`jnfl%NTR}{afg\MWYj}q:;<<2:>00:?lht|Vzb|hbfnd-F\ZusinoTma{Poq0\ip~789:7<3?0=33:44f3`dxxR~fpdnjj`)BPVymjkPamw\ku4Xe|r;<=>310<1f>oi{}U{e}kciog,A]Yt|hmnSlbz_nr1[hs89:;03l5fnrv\tlvbd`dn#HVPsucdaZgk}Ve{>Rczx12349746;h0ec}{_qksaioim&OSS~zngd]bhpYhx;Ufyu>?01>27;75i2ceyQiqgomkc(MQUxxlij_`nv[jv5Wds<=>?<06=6g=nfz~T|d~jlhlf+@^X{}kliRocu^ms6Zkrp9:;<1?;>00b?lht|Vzb|hbfnd-F\ZusinoTma{Poq0\ip~789:7=80=b:kmwqYwayogeck EY]ppdabWhf~Sb~=_lw{456748?5=?o4ioqw[uowmecei"KW_rvbc`Yfd|Ud|?Qbuy2345:6>78n7d`|t^rjt`jnfl%NTR}{afg\eisXgy8Taxv?012?538X[^;9m6gasu]smuckago$IUQ|t`ef[djrWfz9S`{w01238419:l1bb~zPphrfhlhb'LRTyohe^coqZiw:Vg~t=>?0=34:ZUP9;k0ec}{_qksaioim&OSS~zngd]bhpYhx;Ufyu>?01>2<;4b3`dxxR~fpdnjj`)BPVymjkPamw\ku4Xe|r;<=>319<\WR75i2ceyQiqgomkc(MQUxxlij_`nv[jv5Wds<=>?<0;=6`=nfz~T|d~jlhlf+@^X{}kliRocu^ms6Zkrp9:;<1?6>^QT57?>3c8mkusWyc{iagae.G[[vrfolUj`xQ`p3]nq}67896:2<l5fnrv\tlvbd`dn#HVPsucdaZgk}Ve{>Rczx12349466;o0ec}{_qksaioim&OSS~zngd]bhpYhx;Ufyu>?01>15;YT_88j7d`|t^rjt`jnfl%NTR}{afg\eisXgy8Taxv?012?6785m2ceyQiqgomkc(MQUxxlij_`nv[jv5Wds<=>?<30=[VQ6:h1bb~zPphrfhlhb'LRTyohe^coqZiw:Vg~t=>?0=00:7c325<1a>oi{}U{e}kciog,A]Yt|hmnSlbz_nr1[hs89:;0?:1_RU26d=nfz~T|d~jlhlf+@^X{}kliRocu^ms6Zkrp9:;<1<:>3g8mkusWyc{iagae.G[[vrfolUj`xQ`p3]nq}67896993Q\W00b?lht|Vzb|hbfnd-F\ZusinoTma{Poq0\ip~789:7>;0=e:kmwqYwayogeck EY]ppdabWhf~Sb~=_lw{45674;<5S^Y>2`9jjvrXx`zn`d`j/DZ\wqg`mVkgyRa2^ov|567858<2?k4ioqw[uowmecei"KW_rvbc`Yfd|Ud|?Qbuy2345:5?7UX[<9WZ]:>l5fnrv\tlvbd`dn#HVPsucdaZgk}Ve{>Rczx123494>6;o0ec}{_qksaioim&OSS~zngd]bhpYhx;Ufyu>?01>1=;YT_8827d`|t^rjt`jnfl%NTR}{afg\eisXgy8Taxv?012?6;4f3`dxxR~fpdnjj`)BPVymjkPamw\ku4Xe|r;<=>32?31e>oi{}U{e}kciog,A]Yt|hmnSlbz_nr1[hs89:;0>>12d9jjvrXx`zn`d`j/DZ\wqg`mVkgyRa2^ov|567859;2R]X13c8mkusWyc{iagae.G[[vrfolUj`xQ`p3]nq}678968=345fnrv\tlvbd`dn#HVPsucdaZgk}Ve{>Rczx1234959:h1bb~zPphrfhlhb'LRTyohe^coqZiw:Vg~t=>?0=1=57?3c8mkusWyc{iagae.G[[vrfolUj`xQ`p3]nq}67896?2<<6;hlppZvnxlfbbh!JX^qwebcXieTc}?<7<1e>oi{}U{e}kciog,A]Yt|hmnSlbz_nr1[hs89:;0;0>289jjvrXx`zn`d`j/DZ\wqg`mVkgyRa2^ov|56785=5>l5fnrv\tlvbd`dn#HVPsucdaZgk}Ve{>Rczx12349199;30ec}{_qksaioim&OSS~zngd]bhpYhx;Ufyu>?01>;:7g00:?lht|Vzb|hbfnd-F\ZusinoTma{Poq0\ip~789:7531?07?lht|Vzb|hbfnd-F\ZusinoTma{Poq0\w9756;>0ec}{_qksaioim&OSS~zngd]bhpYhx;Ux0<=1259jjvrXx`zn`d`j/DZ\wqg`mVkgyRa2^q?5=85<2ceyQiqgomkc(MQUxxlij_`nv[jv5Wz6:53<;;hlppZvnxlfbbh!JX^qwebcXieTc}95fnrv\tlvbd`dn#HVPsucdaZgk}Ve{>R}323<10>oi{}U{e}kciog,A]Yt|hmnSlbz_nr1[v:5;78?7d`|t^rjt`jnfl%NTR}{afg\eisXgy8T1<;>368mkusWyc{iagae.G[[vrfolUj`xQ`p3]p8739:=1bb~zPphrfhlhb'LRTyohe^coqZiw:Vy7>;0=4:kmwqYwayogeck EY]ppdabWhf~Sb~=_r>13;433`dxxR~fpdnjj`)BPVymjkPamw\ku4X{5832?:4ioqw[uowmecei"KW_rvbc`Yfd|Ud|?Q|<3;=66=nfz~T|d~jlhlf+@^X{}kliRocu^ms6Zu;:7887d`|t^rjt`jnfl%NTR}{afg\eisXgy8T1=1229jjvrXx`zn`d`j/DZ\wqg`mVkgyRa2^q?0;443`dxxR~fpdnjj`)BPVymjkPamw\ku4X{5?5>>5fnrv\tlvbd`dn#HVPsucdaZgk}Ve{>R}36?00?lht|Vzb|hbfnd-F\ZusinoTma{Poq0\w919:l1bb~zPphrfhlhb'LRTyohe^awviYfd`meSakit^ov|5679:80ec}{_qksaioim&OSS~zngd]`pwjXieclbRbjfu]nq}6788UX[<i5fnrv\tlvbd`dn#HVPsucdaZeszeUj`xQnde]nq}6788;9>i5fnrv\tlvbd`dn#HVPsucdaZeszeUj`xQnde]nq}67888?>h5fnrv\tlvbd`dn#HVPsucdaZeszeUj`xQnde]nq}67888?=>>4ioqw[uowmecei"KW_rvbc`Yd|{fTma{Paef\ip~789;98Rh:2e9jjvrXx`zn`d`j/DZ\wqg`mVi~aQnlt]b`aYj}q:;<<;:309jjvrXx`zn`d`j/DZ\wqg`mVi~aQnlt]b`aYj}q:;<<;:_RU36f=nfz~T|d~jlhlf+@^X{}kliRm{rm]bhpYflmUfyu>?00:1a>oi{}U{e}kciog,A]Yt|hmnSnz}l^coqZckVoeS`{w012275=nfz~T|d~jlhlf+@^X{}kliRm{rm]bhpYbpjUnbRczx123547482ceyQiqgomkc(MQUxxlij_bvqhZgk}VosoRka_lw{45669;9;7d`|t^rjt`jnfl%NTR}{afg\gqtkWhf~Shvl_dl\ip~789;8:>>4ioqw[uowmecei"KW_rvbc`Yd|{fTma{Peya\akYj}q:;<<:>319jjvrXx`zn`d`j/DZ\wqg`mVi~aQnlt]f|fYbfVg~t=>?14605>oi{}U{e}kciog,A]Yt|hmnSnz}l^coqZir|zogS`{w01228584;2ceyQiqgomkc(MQUxxlij_bvqhZgk}Ve~x~kc_lw{4566494:=>=4ioqw[uowmecei"KW_rvbc`Yd|{fTma{PotvpaiYj}q:;<<2?>2707>oi{}U{e}kciog,A]Yt|hmnSnz}l^coqZir|zogS`{w01228583?:90ec}{_qksaioim&OSS~zngd]`pwjXieTcxz|em]nq}67886;2;?<1:kmwqYwayogeck EY]ppdabWj~y`Rocu^mvpvckWds<=>><0<07>oi{}U{e}kciog,A]Yt|hmnSnz}l^coqZir|zogS`{w012284869:>0ec}{_qksaioim&OSS~zngd]`pwjXieTcxz|em]nq}67886:2379jjvrXx`zn`d`j/DZ\wqg`mVi~aQnlt]lqqubdVg~t=>?1=3=54Ya=:90ec}{_qksaioim&OSS~zngd]`pwjXieTcxz|em]nq}67886:299<3:kmwqYwayogeck EY]ppdabWj~y`Rocu^mvpvckWds<=>><0<626598=6gasu]smuckago$IUQ|t`ef[frudVkgyRaztrgo[hs89::0?0<4:kmwqYwayogeck EY]ppdabWj~y`Rocu^mvpvckWds<=>><3<275543`dxxR~fpdnjj`)BPVymjkPcupo[djrWfhbPmtz3457;:789?:5fnrv\tlvbd`dn#HVPsucdaZeszeUj`xQ`uuqfhZkrp9:;=1<123]PS5543`dxxR~fpdnjj`)BPVymjkPcupo[djrWfhbPmtz3457;:7?8?>5fnrv\tlvbd`dn#HVPsucdaZeszeUj`xQ`uuqfhZkrp9:;=1<17710?lht|Vzb|hbfnd-F\ZusinoToy|c_`nv[jss{lfTaxv?013?6;?>:h1bb~zPphrfhlhb'LRTyohe^awviYekVddxRczx12357e?000275=nfz~T|d~jlhlf+@^X{}kliRm{rm]agZhh|Vg~t=>?133\WR65m2ceyQiqgomkc(MQUxxlij_bvqhZddWgeS`{w0122[VQ7:m1bb~zPphrfhlhb'LRTyohe^awviYekVyyoRczx1235969:l1bb~zPphrfhlhb'LRTyohe^awviYekVyyoRczx12359699;n0ec}{_qksaioim&OSS~zngd]`pwjXjjUx~nQbuy2344:66;o0ec}{_qksaioim&OSS~zngd]`pwjXjjUx~nQbuy2344:6688j7d`|t^rjt`jnfl%NTR}{afg\gqtkWkxjbnfPmtz34575m2ceyQiqgomkc(MQUxxlij_bvqhZduigicS`{w0122[VQ7:o1bb~zPphrfhlhb'LRTyohe^awviYeq}oTicQmyq]nq}67889:7d`|t^rjt`jnfl%NTR}{afg\gqtkWksiRka_c{s[hs89::=<=<;hlppZvnxlfbbh!JX^qwebcXk}xgSow{e^gm[gwWds<=>>_RU26g=nfz~T|d~jlhlf+@^X{}kliRm{rm]gi`kXmgUfyu>?000`?lht|Vzb|hbfnd-F\ZusinoToy|c_eofiZciWds<=>>13`8mkusWyc{iagae.G[[vrfolUhxbPdlgn[rcXe|r;<=?=c:kmwqYwayogeck EY]ppdabWj~y`Rjbel]taZkrp9:;=<?1238mkusWyc{iagae.G[[vrfolUhxbPeya\mijbohfTaxv?0132563;4ioqw[uowmecei"KW_rvbc`Yd|{fTiumPimnfcdjXe|r;<=?>1^QT565oi{}U{e}kciog,A]Yt|hmnSnz}l^g{gZu~{jkg`Rczx123544c3`dxxR~fpdnjj`)BPVymjkPcupo[osjxVfdbjQbuy23444b3`dxxR~fpdnjj`)BPVymjkPcupo[osjxVfdbjQbuy23447502ceyQiqgomkc(MQUxxlij_bvqhZlreyUfyu>?000:?lht|Vzb|hbfnd-F\ZusinoToy|c_kwntZkrp9:;=<>319jjvrXx`zn`d`j/DZ\wqg`mVi~aQco`f\wlaimmUfyu>?0031a>oi{}U{e}kciog,A]Yt|hmnSnz}l^ovhZgdklyxS`{w012277=nfz~T|d~jlhlf+@^X{}kliRm{rm]nqiYfkjoxRczx1235ZUP9::0ec}{_qksaioim&OSS~zngd]`pwjXe|fTddb`_rgo[hs89::??5fnrv\tlvbd`dn#HVPsucdaZeszeUfyaQgimm\w`jXe|r;<=?>0208mkusWyc{iagae.G[[vrfolUhxbPmtn\lljhWzogS`{w012254553`dxxR~fpdnjj`)BPVymjkPcupo[hskWacgcR}jl^ov|5679=;9j6gasu]smuckago$IUQ|t`ef[frudVg~`Rffln]taZkrp9:;=>=4ioqw[uowmecei"KW_rvbc`Yd|{fTaxbPhhnl[rcXe|r;<=?PSV204>oi{}U{e}kciog,A]Yt|hmnSnz}l^ovhZkrdVnbzcQbuy2344563`dxxR~fpdnjj`)BPVymjkPcupo[hskWdgSigyn^ov|567988h7d`|t^rjt`jnfl%NTR}{afg\gqtkWdgS~Qzn^ov|5679;n0ec}{_qksaioim&OSS~zngd]`pwjXe|fTR{a_lw{45669;n0ec}{_qksaioim&OSS~zngd]`pwjXe|fTyo}t^ov|5679;o0ec}{_qksaioim&OSS~zngd]`pwjXe|fTyo}t^ov|567988h7d`|t^rjt`jnfl%NTR}{afg\gqtkW{olSagak^ov|5679;o0ec}{_qksaioim&OSS~zngd]`pwjXzlmT`d`d_lw{45669<8o7d`|t^rjt`jnfl%NTR}{afg\gqtkW{olSagak^ov|5679;8n7d`|t^rjt`jnfl%NTR}{afg\gqtkW{olSagak^ov|5679:88>6gasu]smuckago$IUQ|t`ef[frudVxnkRbfnj]nq}678899S^Y>2e9jjvrXx`zn`d`j/DZ\wqg`mVi~aQ|hhdw[gwWds<=>>309jjvrXx`zn`d`j/DZ\wqg`mVi~aQ|hhdw[gwWds<=>>_RU376=nfz~T|d~jlhlf+@^X{}kliRm{rm]pll`sWflmhzPmtz3457;979<7d`|t^rjt`jnfl%NTR}{afg\gqtkWzbbjyQ`fgqfpZkrp9:;=1?1_RU275=nfz~T|d~jlhlf+@^X{}kliRm{rm]pmbhXmq~Tnt~Pmtz3457492ceyQiqgomkc(MQUxxlij_bvqhZunogUntyQmyq]nq}6788;9o6gasu]smuckago$IUQ|t`ef[frudV}d~i?349jjvrXx`zn`d`j/DZ\wqg`mVi~aQxpup\wwetmeU;S`{w0123[VQ7:<1bb~zPphrfhlhb'LRTyohe^gsgZiu89:;Sd`y279jjvrXx`zn`d`j/DZ\wqg`mVo{oRa}0123[lhq98h0ec}{_qksaioim&OSS~zngd]f|f16j2ceyQiqgomkc(MQUxxlij_dz`=7>1289jjvrXx`zn`d`j/DZ\wqg`mVzjSbhi_lw{4566494:>55fnrv\tlvbd`dn#HVPsucdaZvfWflmS`{w0122848512ceyQiqgomkc(MQUxxlij_qc\kc`Xe|r;<=?31?316>oi{}U{e}kciog,A]Yt|hmnSkh_vrwv969::1bb~zPphrfhlhb'LRTyohe^pfcZqw|{6;2<<=;hlppZvnxlfbbh!JX^qwebcXzlmT{}z}<0<17>oi{}U{e}kciog,A]Yt|hmnSkh_vrwv9799;80ec}{_qksaioim&OSS~zngd]qabYpx}x7>3<<;hlppZvnxlfbbh!JX^qwebcXzlmT{}z}<3<267=nfz~T|d~jlhlf+@^X{}kliR|jg^uspw:46;90ec}{_qksaioim&OSS~zngd]qabYpx}x7?3?=2:kmwqYwayogeck EY]ppdabW{olSz~{r=6=66=nfz~T|d~jlhlf+@^X{}kliR|jg^uspw:368837d`|t^rjt`jnfl%NTR}{afg\v`aX{ciRczx12357g>100b?lht|Vzb|hbfnd-F\ZusinoT~hiPwskwaZkrp9:;=??=a:kmwqYwayogeck EY]ppdabW{olSz|ftd]nq}6788>:>h5fnrv\tlvbd`dn#HVPsucdaZtboV}yeykPmtz345739VY\>?o4ioqw[uowmecei"KW_rvbc`YumnU|~dzj_lw{4566>08j7d`|t^rjt`jnfl%NTR}{afg\v`aX{ciRczx1235=55<2ceyQiqgomkc(MQUxxlij_sgpqir;87UX[=<;;hlppZvnxlfbbh!JX^qwebcXzly~`y2?>^QT570^QT5ZA5<2ceyQiqgomkc(MQUxxlij_sgpqir;87UX[?<9;hlppZvnxlfbbh!JX^qwebcXzly~`y2?>^QT6Z@5>2ceyQiqgomkc(MQUxxlij_sgpqir;87UX[?QH209jjvrXx`zn`d`j/DZ\wqg`mVxnxb{<02=61=nfz~T|d~jlhlf+@^X{}kliR|jstnw84699889:6gasu]smuckago$IUQ|t`ef[wct}e~7==0>13]E63=nfz~T|d~jlhlf+@^X{}kliR|jstnw8469988TK?=4ioqw[uowmecei"KW_rvbc`Yumzgx1??>0017>oi{}U{e}kciog,A]Yt|hmnSk|umv?5582<;90ec}{_qksaioim&OSS~zngd]qavsk|5;;2;9=1:kmwqYwayogeck EY]ppdabW{oxyaz310<10>oi{}U{e}kciog,A]Yt|hmnSk|umv?54869;8=7d`|t^rjt`jnfl%NTR}{afg\v`urd}6:=3?>2^D12>oi{}U{e}kciog,A]Yt|hmnSk|umv?54869;UL>>5fnrv\tlvbd`dn#HVPsucdaZtb{|f025;00:81bb~zPphrfhlhb'LRTyohe^pfwpjs4885>95fnrv\tlvbd`dn#HVPsucdaZtb{|f0<<110012>oi{}U{e}kciog,A]Yt|hmnSk|umv?57869;UM>;5fnrv\tlvbd`dn#HVPsucdaZtb{|f0<<1100\C75>5fnrv\tlvbd`dn#HVPsucdaZtb{|f0<=11300?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>27;00:>1bb~zPphrfhlhb'LRTyohe^pfwpjs4895;;Q\W104?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>27;11WZ]:><5fnrv\tlvbd`dn#HVPsucdaZtb{|f0<:1259jjvrXx`zn`d`j/DZ\wqg`mVxnxb{<06=5445;2ceyQiqgomkc(MQUxxlij_sgpqir;9=4:>?=4ioqw[uowmecei"KW_rvbc`Yumzgx1?;>7513>oi{}U{e}kciog,A]Yt|hmnSk|umv?5180>VY\64\WR7592ceyQiqgomkc(MQUxxlij_sgpqir;9<4986gasu]smuckago$IUQ|t`ef[wct}e~7=80>1300?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>21;75::1bb~zPphrfhlhb'LRTyohe^pfwpjs48?5::<8;hlppZvnxlfbbh!JX^qwebcXzly~`y2>5?55[VQ7:>1bb~zPphrfhlhb'LRTyohe^pfwpjs48?5;;Q\W002?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>22;433`dxxR~fpdnjj`)BPVymjkPrdqvhq:6>7;:>?=4ioqw[uowmecei"KW_rvbc`Yumzgx1?9>0017>oi{}U{e}kciog,A]Yt|hmnSk|umv?5381?;=0ec}{_qksaioim&OSS~zngd]qavsk|5;=2:8PSV213>oi{}U{e}kciog,A]Yt|hmnSk|umv?5380>VY\=??4ioqw[uowmecei"KW_rvbc`Yumzgx1?8>368mkusWyc{iagae.G[[vrfolUyi~{ct=34:475::1bb~zPphrfhlhb'LRTyohe^pfwpjs48=5=?<<;hlppZvnxlfbbh!JX^qwebcXzly~`y2>7?4462=nfz~T|d~jlhlf+@^X{}kliR|jstnw8419??UX[=<8;hlppZvnxlfbbh!JX^qwebcXzly~`y2>7?55[VQ6:81bb~zPphrfhlhb'LRTyohe^pfwpjs4825>95fnrv\tlvbd`dn#HVPsucdaZtb{|f0<6110017>oi{}U{e}kciog,A]Yt|hmnSk|umv?5=86:;90ec}{_qksaioim&OSS~zngd]qavsk|5;32;9=7:kmwqYwayogeck EY]ppdabW{oxyaz319<42ZUP8;=0ec}{_qksaioim&OSS~zngd]qavsk|5;32:8PSV315>oi{}U{e}kciog,A]Yt|hmnSk|umv?5<85<2ceyQiqgomkc(MQUxxlij_sgpqir;904:=?<<;hlppZvnxlfbbh!JX^qwebcXzly~`y2>9?3166=nfz~T|d~jlhlf+@^X{}kliR|jstnw84?9>>8<7d`|t^rjt`jnfl%NTR}{afg\v`urd}6:5399_RU362=nfz~T|d~jlhlf+@^X{}kliR|jstnw84?9??UX[<>318mkusWyc{iagae.G[[vrfolUyi~{ct=3=5445:2ceyQiqgomkc(MQUxxlij_sgpqir;97;9>?5fnrv\tlvbd`dn#HVPsucdaZtb{|f0<097348mkusWyc{iagae.G[[vrfolUyi~{ct=3=33YT_98=7d`|t^rjt`jnfl%NTR}{afg\v`urd}6:2:8PSV315>oi{}U{e}kciog,A]Yt|hmnSk|umv?6585<2ceyQiqgomkc(MQUxxlij_sgpqir;:94:=?<<;hlppZvnxlfbbh!JX^qwebcXzly~`y2=0?3166=nfz~T|d~jlhlf+@^X{}kliR|jstnw8769>>8<7d`|t^rjt`jnfl%NTR}{afg\v`urd}69<399_RU362=nfz~T|d~jlhlf+@^X{}kliR|jstnw8769??UX[<<>;hlppZvnxlfbbh!JX^qwebcXzly~`y2=1?07?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>15;76:;90ec}{_qksaioim&OSS~zngd]qavsk|58:2<<=3:kmwqYwayogeck EY]ppdabW{oxyaz320<5371=7:kmwqYwayogeck EY]ppdabW{oxyaz320<42ZUP9;;0ec}{_qksaioim&OSS~zngd]qavsk|5892?:4ioqw[uowmecei"KW_rvbc`Yumzgx1<=>03166=nfz~T|d~jlhlf+@^X{}kliR|jstnw87499;887d`|t^rjt`jnfl%NTR}{afg\v`urd}69>388229jjvrXx`zn`d`j/DZ\wqg`mVxnxb{<30=33463`dxxR~fpdnjj`)BPVymjkPrdqvhq:5;78?7d`|t^rjt`jnfl%NTR}{afg\v`urd}69?3?>2318mkusWyc{iagae.G[[vrfolUyi~{ct=00:445;2ceyQiqgomkc(MQUxxlij_sgpqir;::4=;?=4ioqw[uowmecei"KW_rvbc`Yumzgx1<<>6415>oi{}U{e}kciog,A]Yt|hmnSk|umv?6185<2ceyQiqgomkc(MQUxxlij_sgpqir;:=4:=?<<;hlppZvnxlfbbh!JX^qwebcXzly~`y2=4?3166=nfz~T|d~jlhlf+@^X{}kliR|jstnw8729>>887d`|t^rjt`jnfl%NTR}{afg\v`urd}698399209jjvrXx`zn`d`j/DZ\wqg`mVxnxb{<37=61=nfz~T|d~jlhlf+@^X{}kliR|jstnw87399889?6gasu]smuckago$IUQ|t`ef[wct}e~7>80>2318mkusWyc{iagae.G[[vrfolUyi~{ct=06:315;2ceyQiqgomkc(MQUxxlij_sgpqir;:<4<:??4ioqw[uowmecei"KW_rvbc`Yumzgx1<9>368mkusWyc{iagae.G[[vrfolUyi~{ct=05:475::1bb~zPphrfhlhb'LRTyohe^pfwpjs4;<5=?<<;hlppZvnxlfbbh!JX^qwebcXzly~`y2=6?4466=nfz~T|d~jlhlf+@^X{}kliR|jstnw8709??8:7d`|t^rjt`jnfl%NTR}{afg\v`urd}69;3<;;hlppZvnxlfbbh!JX^qwebcXzly~`y2=7?32675:097318mkusWyc{iagae.G[[vrfolUyi~{ct=04:20592ceyQiqgomkc(MQUxxlij_sgpqir;:14986gasu]smuckago$IUQ|t`ef[wct}e~7>50>1300?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>1<;75::1bb~zPphrfhlhb'LRTyohe^pfwpjs4;25::<<;hlppZvnxlfbbh!JX^qwebcXzly~`y2=8?5564=nfz~T|d~jlhlf+@^X{}kliR|jstnw87?9:=1bb~zPphrfhlhb'LRTyohe^pfwpjs4;35=<<=3:kmwqYwayogeck EY]ppdabW{oxyaz328<26756?=9?6gasu]smuckago$IUQ|t`ef[wct}e~7>4086328mkusWyc{iagae.G[[vrfolUyi~{ct=0=66=nfz~T|d~jlhlf+@^X{}kliR|jstnw87869;897d`|t^rjt`jnfl%NTR}{afg\v`urd}692<<=2:kmwqYwayogeck EY]ppdabW{oxyaz32?4463=nfz~T|d~jlhlf+@^X{}kliR|jstnw8780>VY\2348mkusWyc{iagae.G[[vrfolUyi~{ct=13:475WO8=7d`|t^rjt`jnfl%NTR}{afg\v`urd}68<3?>2^E17>oi{}U{e}kciog,A]Yt|hmnSk|umv?7586:;90ec}{_qksaioim&OSS~zngd]qavsk|59;28:=3:kmwqYwayogeck EY]ppdabW{oxyaz331<5375<9=6gasu]smuckago$IUQ|t`ef[wct}e~7?<0=4:kmwqYwayogeck EY]ppdabW{oxyaz330<257443`dxxR~fpdnjj`)BPVymjkPrdqvhq:497;9>>5fnrv\tlvbd`dn#HVPsucdaZtb{|f0>?16600?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>05;11:91bb~zPphrfhlhb'LRTyohe^pfwpjs4:49?6gasu]smuckago$IUQ|t`ef[wct}e~7?3?>2308mkusWyc{iagae.G[[vrfolUyi~{ct=1=57453`dxxR~fpdnjj`)BPVymjkPrdqvhq:46?=9:6gasu]smuckago$IUQ|t`ef[wct}e~7?399_RU363=nfz~T|d~jlhlf+@^X{}kliR|jstnw8680>VY\=?>4ioqw[uowmecei"KW_rvbc`Yumzgx1:1229jjvrXx`zn`d`j/DZ\wqg`mVxnxb{<5<257453`dxxR~fpdnjj`)BPVymjkPrdqvhq:36889>6gasu]smuckago$IUQ|t`ef[wct}e~78388279jjvrXx`zn`d`j/DZ\wqg`mVxnxb{<5<42ZUP8;<0ec}{_qksaioim&OSS~zngd]qavsk|5>5;;Q\W003?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>6:756gasu]smuckago$IUQ|t`ef[wct}e~793?=239jjvrXx`zn`d`j/DZ\wqg`mVxnxb{<4<537064\WR7582ceyQiqgomkc(MQUxxlij_sgpqir;>7887d`|t^rjt`jnfl%NTR}{afg\v`urd}6=2>8=7d`|t^rjt`jnfl%NTR}{afg\v`urd}6=2:8PSV212>oi{}U{e}kciog,A]Yt|hmnSk|umv?2;11WZ]:>=5fnrv\tlvbd`dn#HVPsucdaZtb{|f0:0=3:kmwqYwayogeck EY]ppdabW{oxyaz37?3267295fnrv\tlvbd`dn#HVPsucdaZtb{|f0:0>13012>oi{}U{e}kciog,A]Yt|hmnSk|umv?3;76:Vl>>?5fnrv\tlvbd`dn#HVPsucdaZtb{|f0:097328mkusWyc{iagae.G[[vrfolUyi~{ct=:=66=nfz~T|d~jlhlf+@^X{}kliR|jstnw8=869;897d`|t^rjt`jnfl%NTR}{afg\v`urd}632<<=2:kmwqYwayogeck EY]ppdabW{oxyaz38?4463=nfz~T|d~jlhlf+@^X{}kliR|jstnw8=80>VY\6;90ec}{_qksaioim&OSS~zngd]qavsk|535=<<=2:kmwqYwayogeck EY]ppdabW{oxyaz39?3167=nfz~T|d~jlhlf+@^X{}kliR|jstnw8<81?;<0ec}{_qksaioim&OSS~zngd]qavsk|535;;Q\W105?lht|Vzb|hbfnd-F\ZusinoT~h}zlu>::20X[^;8:6gasu]smuckago$IUQ|t`ef[vnnn}UhxbPsicnpZtilVg~t=>?1=3=72=nfz~T|d~jlhlf+@^X{}kliR}gigv\gqtkWzbjayQ}ne]nq}67886:2<=9;hlppZvnxlfbbh!JX^qwebcX{acmxRm{rm]pldksW{doS`{w01228784?2ceyQiqgomkc(MQUxxlij_rjjbqYd|{fTeobt^pm`Zkrp9:;=1<11248mkusWyc{iagae.G[[vrfolUxddh{_bvqhZuoid~T~cjPmtz3457;;79<7d`|t^rjt`jnfl%NTR}{afg\wmoa|Vi~aQ|h`ow[whcWds<=>><2<273=nfz~T|d~jlhlf+@^X{}kliR}gigv\gqtkWzbjayQ}ne]nq}67886?2>94ioqw[uowmecei"KW_rvbc`Yt``lSnz}l^qkehrXzgnTaxv?013?0;76m2ceyQiqgomkc(MQUxxlij_vpfcZqb:?1bb~zPphrfhlhb'LRTyohe^uqabYpmVY\1g9jjvrXx`zn`d`j/HF\wqg`mVxnkRo30?02?lht|Vzb|hbfnd-J@ZusinoT~hiPa=2=55463`dxxR~fpdnjj`)NLVymjkPrde\e969;;8:7d`|t^rjt`jnfl%BHR}{afg\v`aXi5:5:5<<;hlppZvnxlfbbh!FD^qwebcXzlmTm1>169]E66=nfz~T|d~jlhlf+LBX{}kliR|jg^c?4;0?WN8;7d`|t^rjt`jnfl%BHR}{afg\v`aXi5;;2?<4ioqw[uowmecei"GK_rvbc`YumnUj0<>11101?lht|Vzb|hbfnd-J@ZusinoT~hiPa=33:165<2ceyQiqgomkc(AMUxxlij_sgd[d:687>;SK<;;hlppZvnxlfbbh!FD^qwebcXzlmTm1??>52\C74?8;7d`|t^rjt`jnfl%BHR}{afg\v`aXi5;:2?<4ioqw[uowmecei"GK_rvbc`YumnUj0;>?5fnrv\tlvbd`dn#DJPsucdaZtboVk7=<096328mkusWyc{iagae.KG[vrfolUyijQn<00=67=nfz~T|d~jlhlf+LBX{}kliR|jg^c?57868;80ec}{_qksaioim&COS~zngd]qabYf4885><<=;hlppZvnxlfbbh!FD^qwebcXzlmTm1?=>5216>oi{}U{e}kciog,MAYt|hmnSkh_`>26;01:91bb~zPphrfhlhb'@NTyohe^pfcZg;9:49>6gasu]smuckago$EIQ|t`ef[wc`Wh6:?3??239jjvrXx`zn`d`j/HF\wqg`mVxnkRo312<1574?8?7d`|t^rjt`jnfl%BHR}{afg\v`aXi5;82;8PF368mkusWyc{iagae.KG[vrfolUyijQn<01=23Y@:91bb~zPphrfhlhb'@NTyohe^pfcZg;9=49>6gasu]smuckago$EIQ|t`ef[wc`Wh6:83??239jjvrXx`zn`d`j/HF\wqg`mVxnkRo315<1574?8?7d`|t^rjt`jnfl%BHR}{afg\v`aXi5;?2;8PF368mkusWyc{iagae.KG[vrfolUyijQn<06=23Y@:91bb~zPphrfhlhb'@NTyohe^pfcZg;9<49>6gasu]smuckago$EIQ|t`ef[wc`Wh6:93??239jjvrXx`zn`d`j/HF\wqg`mVxnkRo314<157047\WR75:2ceyQiqgomkc(AMUxxlij_sgd[d:6=795fnrv\tlvbd`dn#DJPsucdaZtboVk7=8094^D10>oi{}U{e}kciog,MAYt|hmnSkh_`>21;03WN8;7d`|t^rjt`jnfl%BHR}{afg\v`aXi5;=2?<4ioqw[uowmecei"GK_rvbc`YumnUj0<811101?lht|Vzb|hbfnd-J@ZusinoT~hiPa=35:775:2ceyQiqgomkc(AMUxxlij_sgd[d:6>7>;>?5fnrv\tlvbd`dn#DJPsucdaZtboVk7=;096328mkusWyc{iagae.KG[vrfolUyijQn<05=67=nfz~T|d~jlhlf+LBX{}kliR|jg^c?52868;80ec}{_qksaioim&COS~zngd]qabYf48=5><<=;hlppZvnxlfbbh!FD^qwebcXzlmTm1?8>5216>oi{}U{e}kciog,MAYt|hmnSkh_`>23;01:91bb~zPphrfhlhb'@NTyohe^pfcZg;9149>6gasu]smuckago$EIQ|t`ef[wc`Wh6:43??239jjvrXx`zn`d`j/HF\wqg`mVxnkRo319<15749=<897d`|t^rjt`jnfl%BHR}{afg\v`aXi5;32;:=0:kmwqYwayogeck IE]ppdabW{olSl2>9?01?lht|Vzb|hbfnd-J@ZusinoT~hiPa=3::465:2ceyQiqgomkc(AMUxxlij_sgd[d:6178:>?5fnrv\tlvbd`dn#DJPsucdaZtboVk7=40;0308mkusWyc{iagae.KG[vrfolUyijQn<0;=237a3`dxxR~fpdnjj`)NLVymjkPrde\e979:81bb~zPphrfhlhb'@NTyohe^pfcZg;97;;><5fnrv\tlvbd`dn#DJPsucdaZtboVk7=3==209jjvrXx`zn`d`j/HF\wqg`mVxnkRo31?4;66=nfz~T|d~jlhlf+LBX{}kliR|jg^c?5;0?WO887d`|t^rjt`jnfl%BHR}{afg\v`aXi5;5:5QH249jjvrXx`zn`d`j/HF\wqg`mVxnkRo31?4;[VQ7:91bb~zPphrfhlhb'@NTyohe^pfcZg;:949>6gasu]smuckago$EIQ|t`ef[wc`Wh69<3??239jjvrXx`zn`d`j/HF\wqg`mVxnkRo321<1574?5fnrv\tlvbd`dn#DJPsucdaZtboVk7><0;0308mkusWyc{iagae.KG[vrfolUyijQn<33=23473`dxxR~fpdnjj`)NLVymjkPrde\e9456;80ec}{_qksaioim&COS~zngd]qabYf4;85==<=;hlppZvnxlfbbh!FD^qwebcXzlmTm1<=>3316>oi{}U{e}kciog,MAYt|hmnSkh_`>16;27:;1bb~zPphrfhlhb'@NTyohe^pfcZg;:;4=:?:4ioqw[uowmecei"GK_rvbc`YumnUj0?<167]E61=nfz~T|d~jlhlf+LBX{}kliR|jg^c?6781>VM9<6gasu]smuckago$EIQ|t`ef[wc`Wh69?3<=;hlppZvnxlfbbh!FD^qwebcXzlmTm1<<>0216>oi{}U{e}kciog,MAYt|hmnSkh_`>17;46:;1bb~zPphrfhlhb'@NTyohe^pfcZg;::4?0ec}{_qksaioim&COS~zngd]qabYf4;95:;QH219jjvrXx`zn`d`j/HF\wqg`mVxnkRo325<16>oi{}U{e}kciog,MAYt|hmnSkh_`>10;77:;1bb~zPphrfhlhb'@NTyohe^pfcZg;:=49=?<4ioqw[uowmecei"GK_rvbc`YumnUj0?:14101?lht|Vzb|hbfnd-J@ZusinoT~hiPa=07:305<2ceyQiqgomkc(AMUxxlij_sgd[d:5<7<=SK<;;hlppZvnxlfbbh!FD^qwebcXzlmTm1<;>74\C7695fnrv\tlvbd`dn#DJPsucdaZtboVk7>8096^D10>oi{}U{e}kciog,MAYt|hmnSkh_`>11;01WN8;7d`|t^rjt`jnfl%BHR}{afg\v`aXi58=2?<4ioqw[uowmecei"GK_rvbc`YumnUj0?811101?lht|Vzb|hbfnd-J@ZusinoT~hiPa=05:775:2ceyQiqgomkc(AMUxxlij_sgd[d:5>7>;>?5fnrv\tlvbd`dn#DJPsucdaZtboVk7>;096368mkusWyc{iagae.KG[vrfolUyijQn<34=23YA:=1bb~zPphrfhlhb'@NTyohe^pfcZg;:?4=:RI=0:kmwqYwayogeck IE]ppdabW{olSl2=7?01?lht|Vzb|hbfnd-J@ZusinoT~hiPa=04:465:2ceyQiqgomkc(AMUxxlij_sgd[d:5?78:>?5fnrv\tlvbd`dn#DJPsucdaZtboVk7>:0;0308mkusWyc{iagae.KG[vrfolUyijQn<35=23433`dxxR~fpdnjj`)NLVymjkPrde\e9406??5fnrv\tlvbd`dn#DJPsucdaZtboVk7>50=1308mkusWyc{iagae.KG[vrfolUyijQn<3:=05453`dxxR~fpdnjj`)NLVymjkPrde\e94?6?<9<6gasu]smuckago$EIQ|t`ef[wc`Wh6953<=;hlppZvnxlfbbh!FD^qwebcXzlmTm1<6>0216>oi{}U{e}kciog,MAYt|hmnSkh_`>1=;46:;1bb~zPphrfhlhb'@NTyohe^pfcZg;:04?<5fnrv\tlvbd`dn#DJPsucdaZtboVk7>387229jjvrXx`zn`d`j/HF\wqg`mVxnkRo32?4;[C443`dxxR~fpdnjj`)NLVymjkPrde\e949>1UL>85fnrv\tlvbd`dn#DJPsucdaZtboVk7>387_RU365=nfz~T|d~jlhlf+LBX{}kliR|jg^c?7585:2ceyQiqgomkc(AMUxxlij_sgd[d:487;;>?5fnrv\tlvbd`dn#DJPsucdaZtboVk7?=0:5368mkusWyc{iagae.KG[vrfolUyijQn<22=10YA:=1bb~zPphrfhlhb'@NTyohe^pfcZg;;94>9RI=2:kmwqYwayogeck IE]ppdabW{olSl2<0?4765=nfz~T|d~jlhlf+LBX{}kliR|jg^c?7485:2ceyQiqgomkc(AMUxxlij_sgd[d:497;;>?5fnrv\tlvbd`dn#DJPsucdaZtboVk7?<0=1308mkusWyc{iagae.KG[vrfolUyijQn<23=05453`dxxR~fpdnjj`)NLVymjkPrde\e9566?<:j6gasu]smuckago$EIQ|t`ef[wc`Wh682??4ioqw[uowmecei"GK_rvbc`YumnUj0>0>0338mkusWyc{iagae.KG[vrfolUyijQn<2<06777:\C730215>oi{}U{e}kciog,MAYt|hmnSkh_`>7:64592ceyQiqgomkc(AMUxxlij_sgd[d:36?29?6gasu]smuckago$EIQ|t`ef[wc`Wh6?2;6PF318mkusWyc{iagae.KG[vrfolUyijQn<5<5>f:kmwqYwayogeck IE]ppdabW{olSl2:>338mkusWyc{iagae.KG[vrfolUyijQn<4<2477oi{}U{e}kciog,MAYt|hmnSkh_`>6:3>XO;?0ec}{_qksaioim&COS~zngd]qabYf4<4=4R]X00d8mkusWyc{iagae.KG[vrfolUyijQn<7<15>oi{}U{e}kciog,MAYt|hmnSkh_`>5:46592ceyQiqgomkc(AMUxxlij_sgd[d:16:89=6gasu]smuckago$EIQ|t`ef[wc`Wh6=2;6=3:kmwqYwayogeck IE]ppdabW{olSl29>7:\B75oi{}U{e}kciog,MAYt|hmnSkh_`>4:76<5fnrv\tlvbd`dn#DJPsucdaZtboVk7;3==209jjvrXx`zn`d`j/HF\wqg`mVxnkRo37?4;60=nfz~T|d~jlhlf+LBX{}kliR|jg^c?3;0?WZ];=k5fnrv\tlvbd`dn#DJPsucdaZtboVk743<>;hlppZvnxlfbbh!FD^qwebcXzlmTm1611102?lht|Vzb|hbfnd-J@ZusinoT~hiPa=:=64463`dxxR~fpdnjj`)NLVymjkPrde\e9>9<98>7d`|t^rjt`jnfl%BHR}{afg\v`aXi5258=Q\W102?lht|Vzb|hbfnd-J@ZusinoT~hiPa=:=237a3`dxxR~fpdnjj`)NLVymjkPrde\e9?9:81bb~zPphrfhlhb'@NTyohe^pfcZg;17;;><5fnrv\tlvbd`dn#DJPsucdaZtboVk753:?229jjvrXx`zn`d`j/HF\wqg`mVxnkRo39?63[C443`dxxR~fpdnjj`)NLVymjkPrde\e9?9<9UL><5fnrv\tlvbd`dn#DJPsucdaZtboVk753891g9jjvrXx`zn`d`j/HF\wqg`mVxnkRl30?02?lht|Vzb|hbfnd-J@ZusinoT~hiPb=2=55463`dxxR~fpdnjj`)NLVymjkPrde\f969;;8:7d`|t^rjt`jnfl%BHR}{afg\v`aXj5:5:5<<;hlppZvnxlfbbh!FD^qwebcXzlmTn1>169]E66=nfz~T|d~jlhlf+LBX{}kliR|jg^`?4;0?WN8;7d`|t^rjt`jnfl%BHR}{afg\v`aXj5;;2?<4ioqw[uowmecei"GK_rvbc`YumnUi0<>11101?lht|Vzb|hbfnd-J@ZusinoT~hiPb=33:775:2ceyQiqgomkc(AMUxxlij_sgd[g:687?>>?5fnrv\tlvbd`dn#DJPsucdaZtboVh7==094328mkusWyc{iagae.KG[vrfolUyijQm<03=67=nfz~T|d~jlhlf+LBX{}kliR|jg^`?54868;80ec}{_qksaioim&COS~zngd]qabYe48;5><<=;hlppZvnxlfbbh!FD^qwebcXzlmTn1?>>4716>oi{}U{e}kciog,MAYt|hmnSkh_c>25;03:91bb~zPphrfhlhb'@NTyohe^pfcZd;9;49>6gasu]smuckago$EIQ|t`ef[wc`Wk6:>3??239jjvrXx`zn`d`j/HF\wqg`mVxnkRl313<15743?01?lht|Vzb|hbfnd-J@ZusinoT~hiPb=30:465:2ceyQiqgomkc(AMUxxlij_sgd[g:6;78:>?5fnrv\tlvbd`dn#DJPsucdaZtboVh7=>0:5308mkusWyc{iagae.KG[vrfolUyijQm<01=21473`dxxR~fpdnjj`)NLVymjkPrde\f9736;80ec}{_qksaioim&COS~zngd]qabYe48>5==<=;hlppZvnxlfbbh!FD^qwebcXzlmTn1?;>3316>oi{}U{e}kciog,MAYt|hmnSkh_c>20;32:;1bb~zPphrfhlhb'@NTyohe^pfcZd;9=4=8?>4ioqw[uowmecei"GK_rvbc`YumnUi0<;1239jjvrXx`zn`d`j/HF\wqg`mVxnkRl314<24742;:=4:kmwqYwayogeck IE]ppdabW{olSo2>5?47[C433`dxxR~fpdnjj`)NLVymjkPrde\f9726?>TK?>4ioqw[uowmecei"GK_rvbc`YumnUi0<81239jjvrXx`zn`d`j/HF\wqg`mVxnkRl317<24746?47[C433`dxxR~fpdnjj`)NLVymjkPrde\f9716?>TK?>4ioqw[uowmecei"GK_rvbc`YumnUi0<91239jjvrXx`zn`d`j/HF\wqg`mVxnkRl316<24747?47[C433`dxxR~fpdnjj`)NLVymjkPrde\f9706?>TK?>4ioqw[uowmecei"GK_rvbc`YumnUi0<61239jjvrXx`zn`d`j/HF\wqg`mVxnkRl319<24749:8897d`|t^rjt`jnfl%BHR}{afg\v`aXj5;32;:=4:kmwqYwayogeck IE]ppdabW{olSo2>8?47[C433`dxxR~fpdnjj`)NLVymjkPrde\f97?6?>TK?>4ioqw[uowmecei"GK_rvbc`YumnUi0<71239jjvrXx`zn`d`j/HF\wqg`mVxnkRl318<24749?47[C433`dxxR~fpdnjj`)NLVymjkPrde\f97>6?>TK>0215>oi{}U{e}kciog,MAYt|hmnSkh_c>2:64592ceyQiqgomkc(AMUxxlij_sgd[g:66?29?6gasu]smuckago$EIQ|t`ef[wc`Wk6:2;6PF318mkusWyc{iagae.KG[vrfolUyijQm<0<5=2:kmwqYwayogeck IE]ppdabW{olSo2=0?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6581<;>0ec}{_qksaioim&COS~zngd]qabYe4;:5:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl321<50ZA582ceyQiqgomkc(AMUxxlij_sgd[g:597897d`|t^rjt`jnfl%BHR}{afg\v`aXj58:2<>=2:kmwqYwayogeck IE]ppdabW{olSo2=1?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6481>;>0ec}{_qksaioim&COS~zngd]qabYe4;;5:;QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl320<52ZA582ceyQiqgomkc(AMUxxlij_sgd[g:5:7897d`|t^rjt`jnfl%BHR}{afg\v`aXj5892<>=2:kmwqYwayogeck IE]ppdabW{olSo2=2?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6781<;>0ec}{_qksaioim&COS~zngd]qabYe4;85:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl323<50ZA582ceyQiqgomkc(AMUxxlij_sgd[g:5;7897d`|t^rjt`jnfl%BHR}{afg\v`aXj5882<>=2:kmwqYwayogeck IE]ppdabW{olSo2=3?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6681<;>0ec}{_qksaioim&COS~zngd]qabYe4;95:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl322<50ZA582ceyQiqgomkc(AMUxxlij_sgd[g:5<7897d`|t^rjt`jnfl%BHR}{afg\v`aXj58?2<>=2:kmwqYwayogeck IE]ppdabW{olSo2=4?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6181<;>0ec}{_qksaioim&COS~zngd]qabYe4;>5:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl325<50ZA582ceyQiqgomkc(AMUxxlij_sgd[g:5=7897d`|t^rjt`jnfl%BHR}{afg\v`aXj58>2<>=2:kmwqYwayogeck IE]ppdabW{olSo2=5?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6081<;>0ec}{_qksaioim&COS~zngd]qabYe4;?5:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl324<50ZA582ceyQiqgomkc(AMUxxlij_sgd[g:5>7897d`|t^rjt`jnfl%BHR}{afg\v`aXj58=2<>=2:kmwqYwayogeck IE]ppdabW{olSo2=6?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6381<;>0ec}{_qksaioim&COS~zngd]qabYe4;<5:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl327<50ZA582ceyQiqgomkc(AMUxxlij_sgd[g:5?7897d`|t^rjt`jnfl%BHR}{afg\v`aXj58<2<>=2:kmwqYwayogeck IE]ppdabW{olSo2=7?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6281<;>0ec}{_qksaioim&COS~zngd]qabYe4;=5:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl326<50ZA582ceyQiqgomkc(AMUxxlij_sgd[g:507897d`|t^rjt`jnfl%BHR}{afg\v`aXj5832<>=2:kmwqYwayogeck IE]ppdabW{olSo2=8?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6=81<;>0ec}{_qksaioim&COS~zngd]qabYe4;25:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl329<50ZA582ceyQiqgomkc(AMUxxlij_sgd[g:517897d`|t^rjt`jnfl%BHR}{afg\v`aXj5822<>=2:kmwqYwayogeck IE]ppdabW{olSo2=9?0267=nfz~T|d~jlhlf+LBX{}kliR|jg^`?6<81<;>0ec}{_qksaioim&COS~zngd]qabYe4;35:9QI259jjvrXx`zn`d`j/HF\wqg`mVxnkRl328<50ZA6n2ceyQiqgomkc(AMUxxlij_sgd[g:56;;0ec}{_qksaioim&COS~zngd]qabYe4;4:<<=;hlppZvnxlfbbh!FD^qwebcXzlmTn1=?>7410>oi{}U{e}kciog,MAYt|hmnSkh_c>04;01WO8?7d`|t^rjt`jnfl%BHR}{afg\v`aXj59;2;8PG328mkusWyc{iagae.KG[vrfolUyijQm<23=67=nfz~T|d~jlhlf+LBX{}kliR|jg^`?74868;80ec}{_qksaioim&COS~zngd]qabYe4:;5><<=;hlppZvnxlfbbh!FD^qwebcXzlmTn1=>>7610>oi{}U{e}kciog,MAYt|hmnSkh_c>05;03WO8?7d`|t^rjt`jnfl%BHR}{afg\v`aXj59:2;:PG0d8mkusWyc{iagae.KG[vrfolUyijQm<2<15>oi{}U{e}kciog,MAYt|hmnSkh_c>0:46592ceyQiqgomkc(AMUxxlij_sgd[g:46:89=6gasu]smuckago$EIQ|t`ef[wc`Wk682;6=3:kmwqYwayogeck IE]ppdabW{olSo2<>7:\B750338mkusWyc{iagae.KG[vrfolUyijQm<5<06777:\C4`2><=1:kmwqYwayogeck IE]ppdabW{olSo2:>7:17>oi{}U{e}kciog,MAYt|hmnSkh_c>6:3>XN;90ec}{_qksaioim&COS~zngd]qabYe4<4=4RI>f:kmwqYwayogeck IE]ppdabW{olSo29>338mkusWyc{iagae.KG[vrfolUyijQm<7<2477oi{}U{e}kciog,MAYt|hmnSkh_c>5:3>XO8l0ec}{_qksaioim&COS~zngd]qabYe4>49<6gasu]smuckago$EIQ|t`ef[wc`Wk6<2<<>;hlppZvnxlfbbh!FD^qwebcXzlmTn1911102?lht|Vzb|hbfnd-J@ZusinoT~hiPb=5=77463`dxxR~fpdnjj`)NLVymjkPrde\f919>1;m7d`|t^rjt`jnfl%BHR}{afg\v`aXj525><5fnrv\tlvbd`dn#DJPsucdaZtboVh743??209jjvrXx`zn`d`j/HF\wqg`mVxnkRl38?0264=nfz~T|d~jlhlf+LBX{}kliR|jg^`?<;03::1bb~zPphrfhlhb'@NTyohe^pfcZd;07<<>;hlppZvnxlfbbh!FD^qwebcXzlmTn1716500?lht|Vzb|hbfnd-J@ZusinoT~hiPb=;=21YA::1bb~zPphrfhlhb'@NTyohe^pfcZd;170ec}{_qksaioim&GNAR}{afg-gqtk&mgnaRka209jjvrXx`zn`d`j/LGN[vrfol$hxb!jtos63=nfz~T|d~jlhlf+HCJWz~jkh ltsn-npkwWeeek?64ioqw[uowmecei"CJM^qwebc)k}xg"aand^qjckcc:<1bb~zPphrfhlhb'DOFS~zngd,`pwj)zlmT`d`d279jjvrXx`zn`d`j/LGN[vrfol$hxb!sikepZd~x;h0ec}{_qksaioim&GNAR}{afg-gqtk&zbbjyQ`fgqfpZ6512ceyQiqgomkc(ELGTyohe/awvi(tandTiuzPbxr11>oi{}U{e}kciog,I@KX{}kli#m{rm,tkwb5Wld:h6gasu]smuckago$AHCPsucda+cwkV::h6gasu]smuckago$AHCPsucda+cwkV;:i6gasu]smuckago$AHCPsucda+cwkV;;=h5fnrv\tlvbd`dn#@KB_rvbc`(bxjU:=e:kmwqYwayogeck MDO\wqg`m'o{oR?;1d9jjvrXx`zn`d`j/LGN[vrfol$n|nQ>50g8mkusWyc{iagae.OFIZusino%i}mP173f?lht|Vzb|hbfnd-NAHYt|hmn"h~l_052a>oi{}U{e}kciog,I@KX{}kli#kc^3;5`=nfz~T|d~jlhlf+HCJWz~jkh jpb]2=4b5?j;hlppZvnxlfbbh!BEL]ppdab&lzhS?7>d:kmwqYwayogeck MDO\wqg`m'o{oR=>e:kmwqYwayogeck MDO\wqg`m'o{oR=?1d9jjvrXx`zn`d`j/LGN[vrfol$n|nQ<10f8mkusWyc{iagae.OFIZusino%i}mP40f8mkusWyc{iagae.OFIZusino%i}mP50f8mkusWyc{iagae.OFIZusino%i}mP60f8mkusWyc{iagae.OFIZusino%i}mP70f8mkusWyc{iagae.OFIZusino%i}mP80f8mkusWyc{iagae.OFIZusino%i}mP93;8mkusWyc{iagae.OFIZusino%i{katr]jj+gk}Ve}j?74ioqw[uowmecei"CJM^qwebc)moex~Qfn/coqZsqn;=0ec}{_qksaioim&GNAR}{afg-asci|zUbb#l}e`i1b>oi{}U{e}kciog,I@KX{}kli#kyeovp[lh)lh~jSaand^gqv660ec}{_qksaioim&GNAR}{afg-a}YumzgxR?7259jjvrXx`zn`d`j/LGN[vrfol$ntR|jstnw[4?5;2ceyQiqgomkc(ELGTyohe/g{[wct}e~T>?:4ioqw[uowmecei"CJM^qwebc)mqUyi~{ct^0361=nfz~T|d~jlhlf+HCJWz~jkh jx^pfwpjsW;;986gasu]smuckago$AHCPsucda+cW{oxyazP2307?lht|Vzb|hbfnd-NAHYt|hmn"hvPrdqvhqY5;;>0ec}{_qksaioim&GNAR}{afg-a}YumzgxR<;259jjvrXx`zn`d`j/LGN[vrfol$ntR|jstnw[735<2ceyQiqgomkc(ELGTyohe/g{[wct}e~T>;<;;hlppZvnxlfbbh!BEL]ppdab&lrT~h}zlu]137295fnrv\tlvbd`dn#@KB_rvbc`(bpVxnxb{_3;17>oi{}U{e}kciog,I@KX{}kli#kw_sgpqirX;;>0ec}{_qksaioim&GNAR}{afg-a}YumzgxR=?259jjvrXx`zn`d`j/LGN[vrfol$ntR|jstnw[675;2ceyQiqgomkc(ELGTyohe/g{[wct}e~T8?=4ioqw[uowmecei"CJM^qwebc)mqUyi~{ct^717>oi{}U{e}kciog,I@KX{}kli#kw_sgpqirX>;90ec}{_qksaioim&GNAR}{afg-a}YumzgxR9=3:kmwqYwayogeck MDO\wqg`m'osSk|umv\<75=5fnrv\tlvbd`dn#@KB_rvbc`(wiVemjR?>d:kmwqYwayogeck MDO\wqg`m'zhbR>>d:kmwqYwayogeck MDO\wqg`m'zhbR?>e:kmwqYwayogeck MDO\wqg`m'zhbR??1d9jjvrXx`zn`d`j/LGN[vrfol${ocQ>10g8mkusWyc{iagae.OFIZusino%|n`P133f?lht|Vzb|hbfnd-NAHYt|hmn"}ma_012a>oi{}U{e}kciog,I@KX{}kli#~ln^375`=nfz~T|d~jlhlf+HCJWz~jkh co]214c9?j;hlppZvnxlfbbh!BEL]ppdab&yieS?;>e:kmwqYwayogeck MDO\wqg`m'zhbR<91d9jjvrXx`zn`d`j/LGN[vrfol${ocQ=70g8mkusWyc{iagae.OFIZusino%|n`P293f?lht|Vzb|hbfnd-NAHYt|hmn"}ma_3;2`>oi{}U{e}kciog,I@KX{}kli#~ln^12a>oi{}U{e}kciog,I@KX{}kli#~ln^135`=nfz~T|d~jlhlf+HCJWz~jkh co]054b=i5fnrv\tlvbd`dn#@KB_rvbc`(qiV;==i5fnrv\tlvbd`dn#@KB_rvbc`(qiV;<=i5fnrv\tlvbd`dn#@KB_rvbc`(qiV;3=i5fnrv\tlvbd`dn#@KB_rvbc`(qiV;2=n5fnrv\tlvbd`dn#@KB_rvbc`(qiV8:h6gasu]smuckago$AHCPsucda+pfW;::h6gasu]smuckago$AHCPsucda+pfW;;:h6gasu]smuckago$AHCPsucda+pfW;8:h6gasu]smuckago$AHCPsucda+pfW;9:h6gasu]smuckago$AHCPsucda+pfW;>:h6gasu]smuckago$AHCPsucda+pfW;?:h6gasu]smuckago$AHCPsucda+pfW;<:h6gasu]smuckago$AHCPsucda+pfW;=:h6gasu]smuckago$AHCPsucda+pfW;2:h6gasu]smuckago$AHCPsucda+pfW;3:o6gasu]smuckago$AHCPsucda+pfW:;o7d`|t^rjt`jnfl%FI@Q|t`ef*sgX;9;o7d`|t^rjt`jnfl%FI@Q|t`ef*sgX;8;h7d`|t^rjt`jnfl%FI@Q|t`ef*sgX<8i0ec}{_qksaioim&GNAR}{afg-rdY29j1bb~zPphrfhlhb'DOFS~zngd,ueZ06k2ceyQiqgomkc(ELGTyohe/tb[27d3`dxxR~fpdnjj`)JMDUxxlij.wc\<4e>13;8mkusWyc{iagae.OFIZusinoToy|c_kwntZkrp9:;=?o4ioqw[uowmecei"CJM^qwebcXk}xgSg{bp^ov|567989;7d`|t^rjt`jnfl%FI@Q|t`ef[frudVfdmiQ|iflf`Zkrp9:;=>?4ioqw[uowmecei"CJM^qwebcXk}xgSaand^qjckccWds<=>>13f8mkusWyc{iagae.OFIZusinoToy|c_sgd[ioicVg~t=>?13g8mkusWyc{iagae.OFIZusinoToy|c_sgd[ioicVg~t=>?100f?lht|Vzb|hbfnd-NAHYt|hmnSnz}l^qkmcrXjpzTaxv?0131b>oi{}U{e}kciog,I@KX{}kliRm{rm]pll`sWks{S`{w0122562><0<274=nfz~T|d~jlhlf+HCJWz~jkhQltsn\wlaiWlrSow_lw{4566;;1bb~zPphrfhlhb'DOFS~zngd]`pwjX{`meShv{_c{s[hs89::=?j4ioqw[uowmecei"CJM^qwebcXk}xgSza}d3]fjZkrp9:;=?k4ioqw[uowmecei"CJM^qwebcXk}xgSza}d3]fjZkrp9:;=1219jjvrXx`zn`d`j/LGN[vrfolUomyo311<14>oi{}U{e}kciog,I@KX{}kliRjnt`>25;473`dxxR~fpdnjj`)JMDUxxlij_ecwe9756;:0ec}{_qksaioim&GNAR}{afg\`drf4895>=5fnrv\tlvbd`dn#@KB_rvbc`Yci}k7=90=0:kmwqYwayogeck MDO\wqg`mVnjxl2>5?03?lht|Vzb|hbfnd-NAHYt|hmnSio{a=35:76oi{}U{e}kciog,I@KX{}kliRjnt`>15;473`dxxR~fpdnjj`)JMDUxxlij_ecwe9456;:0ec}{_qksaioim&GNAR}{afg\`drf4;95>=5fnrv\tlvbd`dn#@KB_rvbc`Yci}k7>90=0:kmwqYwayogeck MDO\wqg`mVnjxl2=5?03?lht|Vzb|hbfnd-NAHYt|hmnSio{a=05:76oi{}U{e}kciog,I@KX{}kliRjnt`>05;7a3`dxxR~fpdnjj`)JMDUxxlij_ecwe9599o1bb~zPphrfhlhb'DOFS~zngd]geqg;<7;m7d`|t^rjt`jnfl%FI@Q|t`ef[agsi5?5=k5fnrv\tlvbd`dn#@KB_rvbc`Yci}k7:3?i;hlppZvnxlfbbh!BEL]ppdabWmkm1911g9jjvrXx`zn`d`j/LGN[vrfolUomyo38?3e?lht|Vzb|hbfnd-NAHYt|hmnSio{a=;=63=nfz~T|d~jlhlf+HCJWz~jkhQjpb]lv5678Vcez?94ioqw[uowmecei"CJM^qwebcXmyiTc>?01]jjs75k2ceyQiqgomkc(ELGTyohe^g{[wct}e~Taxv?010?4;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>24;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>25;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>26;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>27;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>20;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>21;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>22;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>23;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>2<;4c3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>2=;4d3`dxxR~fpdnjj`)JMDUxxlij_dz\v`urd}Ufyu>?03>2:7b?2=03:7b?2=02:7b?2=01:7b?2=00:7b?2=07:7b?2=06:7b?2=05:7b?2=04:7b?2=0;:7b?2=0::7e?2=0=6a=nfz~T|d~jlhlf+HCJWz~jkhQjx^pfwpjsWds<=>=<22=6a=nfz~T|d~jlhlf+HCJWz~jkhQjx^pfwpjsWds<=>=<23=6f=nfz~T|d~jlhlf+HCJWz~jkhQjx^pfwpjsWds<=>=<2<1g>oi{}U{e}kciog,I@KX{}kliRkw_sgpqirXe|r;<=<34?0`?lht|Vzb|hbfnd-NAHYt|hmnShvPrdqvhqYj}q:;3a8mkusWyc{iagae.OFIZusinoTiuQ}erwopZkrp9:;>1812b9jjvrXx`zn`d`j/LGN[vrfolUntR|jstnw[hs89:90:0=c:kmwqYwayogeck MDO\wqg`mVosSk|umv\ip~7898743?101a?lht|Vzb|hbfnd-NeabXMQUxxlij.rjjbqYd|{f%eobt^pm`Zgclzi<=>?469jjvrXx`zn`d`j/Lcg`ZC_Wz~jkh |hhdw[frud'ycm`zProf\eabt}k:;<=Qly=0=54YT_9><7d`|t^rjt`jnfl%FmijPEY]ppdab&zbbjyQltsn-wmgj|VxehRokdrwa4567Wjs7>3?>_RU26<=nfz~T|d~jlhlf+HgclVnjxl;P7^cg`5678Vir0<>12b9jjvrXx`zn`d`j/Lcg`Zbf|h?T;Rokd1234Ze~48:5Sz=9:kmwqYwayogeck M`fg[agsi?_b{?548Xz}827d`|t^rjt`jnfl%FmijPd`vb1Z1Ximn;<=>Pcx>26;4d3`dxxR~fpdnjj`)JimnThlzn5^5\eab789:Tot2>2?]qp7?3a8mkusWyc{iagae.Ob`aYci}k>S:Qnde2345Ydq5;82R|{289jjvrXx`zn`d`j/Lcg`Zbf|h?T;Rokd1234Ze~48>5>n5fnrv\tlvbd`dn#@okd^fbpd3X?Vkoh=>?0^az8429W{~956gasu]smuckago$Aljk_ecwe0Y0Whno<=>?_b{?5085k2ceyQiqgomkc(EhnoSio{a4]4[dbc89:;Snw314<\vq4>3`dxxR~fpdnjj`)JimnThlzn5^5\eab789:Tot2>6?0`?lht|Vzb|hbfnd-NeabXlh~j9R9Paef3456Xkp6::3Q}t3;8mkusWyc{iagae.Ob`aYci}k>S:Qnde2345Ydq5;<2?m4ioqw[uowmecei"Cnde]geqg2W>Ujhi>?01]`}9706Vx>45fnrv\tlvbd`dn#@okd^fbpd3X?Vkoh=>?0^az84>9:j1bb~zPphrfhlhb'DkohRjnt`7\3Zgcl9:;oi{}U{e}kciog,IdbcWmkm8Q8_`fg4567Wjs7=40Pru0:?lht|Vzb|hbfnd-NeabXlh~j9R9Paef3456Xkp69<3Ujhi>?01]`}9466;i0ec}{_qksaioim&GjhiQkauc6[2Yflm:;<=Qly=02:Zts:01bb~zPphrfhlhb'DkohRjnt`7\3Zgcl9:;oi{}U{e}kciog,IdbcWmkm8Q8_`fg4567Wjs7>>0=c:kmwqYwayogeck M`fg[agsiPcx>10;Yu|;30ec}{_qksaioim&GjhiQkauc6[2Yflm:;<=Qly=06:7e^pw6<=nfz~T|d~jlhlf+HgclVnjxl;P7^cg`5678Vir0?812b9jjvrXx`zn`d`j/Lcg`Zbf|h?T;Rokd1234Ze~4;<5Sz=9:kmwqYwayogeck M`fg[agsi49o6gasu]smuckago$Aljk_ecwe0Y0Whno<=>?_b{?628Xz}827d`|t^rjt`jnfl%FmijPd`vb1Z1Ximn;<=>Pcx>1<;4d3`dxxR~fpdnjj`)JimnThlzn5^5\eab789:Tot2=8?]qp7?3a8mkusWyc{iagae.Ob`aYci}k>S:Qnde2345Ydq5822R|{299jjvrXx`zn`d`j/Lcg`Zbf|h?T;Rokd1234Ze~4;4956gasu]smuckago$Aljk_ecwe0Y0Whno<=>?_b{?7585k2ceyQiqgomkc(EhnoSio{a4]4[dbc89:;Snw331<\vq4?3`dxxR~fpdnjj`)JimnThlzn5^5\eab789:Tot2<>3`8mkusWyc{iagae.Ob`aYci}k>S:Qnde2345Ydq595Sz=8:kmwqYwayogeck M`fg[agsiPcx>7:Zts:11bb~zPphrfhlhb'DkohRjnt`7\3Zgcl9:;oi{}U{e}kciog,IdbcWmkm8Q8_`fg4567Wjs793Q}t3:8mkusWyc{iagae.Ob`aYci}k>S:Qnde2345Ydq5<5>o5fnrv\tlvbd`dn#@okd^fbpd3X?Vkoh=>?0^az838Xz}837d`|t^rjt`jnfl%FmijPd`vb1Z1Ximn;<=>Pcx>4:7doi{}U{e}kciog,IdbcWmkm8Q8_`fg4567Wjs74355fnrv\tlvbd`dn#@okd^fbpd3X?Vkoh=>?0^az8<85j2ceyQiqgomkc(EhnoSio{a4]4[dbc89:;Snw39?]qp7?3d8mkusWyc{iagae.Ob`aYci}k>S:Qnde2345Yk}}692RGAV^21e>oi{}U{e}kciog,IdbcWmkm8Q8_`fg4567Wqey0<>12`9jjvrXx`zn`d`j/Lcg`Zbf|h?T;Rokd1234Z~hz5;:2?o4ioqw[uowmecei"Cnde]geqg2W>Ujhi>?01]{kw:6:78j7d`|t^rjt`jnfl%FmijPd`vb1Z1Ximn;<=>Pxnp?5685i2ceyQiqgomkc(EhnoSio{a4]4[dbc89:;Sua}<06=6d=nfz~T|d~jlhlf+HgclVnjxl;P7^cg`5678Vrd~1?:>3c8mkusWyc{iagae.Ob`aYci}k>S:Qnde2345Yg{6::349m6gasu]smuckago$Aljk_ecwe0Y0Whno<=>?_ymq84>9:h1bb~zPphrfhlhb'DkohRjnt`7\3Zgcl9:;<0=a:kmwqYwayogeck M`fg[agsil5fnrv\tlvbd`dn#@okd^fbpd3X?Vkoh=>?0^zlv9446;k0ec}{_qksaioim&GjhiQkauc6[2Yflm:;<=Qwos>10;4f3`dxxR~fpdnjj`)JimnThlzn5^5\eab789:Ttb|324<1e>oi{}U{e}kciog,IdbcWmkm8Q8_`fg4567Wqey0?812`9jjvrXx`zn`d`j/Lcg`Zbf|h?T;Rokd1234Z~hz58<2?o4ioqw[uowmecei"Cnde]geqg2W>Ujhi>?01]{kw:5078j7d`|t^rjt`jnfl%FmijPd`vb1Z1Ximn;<=>Pxnp?6<8512ceyQiqgomkc(EhnoSio{a4]4[dbc89:;Sua}<3<1e>oi{}U{e}kciog,IdbcWmkm8Q8_`fg4567Wqey0>>12`9jjvrXx`zn`d`j/Lcg`Zbf|h?T;Rokd1234Z~hz59:2?j4ioqw[uowmecei"Cnde]geqg2W>Ujhi>?01]{kw:497Uyx?74ioqw[uowmecei"Cnde]geqg2W>Ujhi>?01]{kw:46;30ec}{_qksaioim&GjhiQkauc6[2Yflm:;<=Qwos>7:7?3;8mkusWyc{iagae.Ob`aYci}k>S:Qnde2345Yg{6=2?74ioqw[uowmecei"Cnde]geqg2W>Ujhi>?01]{kw:06;30ec}{_qksaioim&GjhiQkauc6[2Yflm:;<=Qwos>;:7?3`8mkusWyc{iagae.Ob`aYwk'dsxRokdrwa4567Wjs7==0=b:kmwqYwayogeck M`fg[ue)fq~Tmij|uc2345Ydq5;:2?l4ioqw[uowmecei"Cnde]sg+h|Vkoh~{m0123[f;9;49n6gasu]smuckago$Aljk_qa-j}rXimnxyo>?01]`}9746;h0ec}{_qksaioim&GjhiQc/l{pZgclzi<=>?_b{?5185j2ceyQiqgomkc(EhnoS}m!nyv\eabt}k:;<=Qly=36:7doi{}U{e}kciog,IdbcWyi%buzPaefpqg6789Uhu1?8>3`8mkusWyc{iagae.Ob`aYwk'dsxRokdrwa4567Wjs7=50=b:kmwqYwayogeck M`fg[ue)fq~Tmij|uc2345Ydq5;22?l4ioqw[uowmecei"Cnde]sg+h|Vkoh~{m0123[f;:949n6gasu]smuckago$Aljk_qa-j}rXimnxyo>?01]`}9466;h0ec}{_qksaioim&GjhiQc/l{pZgclzi<=>?_b{?6785j2ceyQiqgomkc(EhnoS}m!nyv\eabt}k:;<=Qly=00:7doi{}U{e}kciog,IdbcWyi%buzPaefpqg6789Uhu1<:>3`8mkusWyc{iagae.Ob`aYwk'dsxRokdrwa4567Wjs7>;0=b:kmwqYwayogeck M`fg[ue)fq~Tmij|uc2345Ydq58<2?l4ioqw[uowmecei"Cnde]sg+h|Vkoh~{m0123[f;:149n6gasu]smuckago$Aljk_qa-j}rXimnxyo>?01]`}94>6;k0ec}{_qksaioim&GjhiQc/l{pZgclzi<=>?_b{?6;4e3`dxxR~fpdnjj`)JimnT|n axu]b`aurj9:;3c8mkusWyc{iagae.Ob`aYwk'dsxRokdrwa4567Wjs783?01]`}909:h1bb~zPphrfhlhb'DkohR~l.ozw[dbc{|h;<=>Pcx>4:7gn5fnrv\tlvbd`dn#@okd^r`*k~sWhnoxl?012\|jt;9849o6gasu]smuckago$Aljk_qa-j}rXimnxyo>?01]{kw:6:78h7d`|t^rjt`jnfl%FmijPpb,m|qYflmy~n=>?0^zlv9746;i0ec}{_qksaioim&GjhiQc/l{pZgclzi<=>?_ymq8429:j1bb~zPphrfhlhb'DkohR~l.ozw[dbc{|h;<=>Pxnp?5085k2ceyQiqgomkc(EhnoS}m!nyv\eabt}k:;<=Qwos>22;4d3`dxxR~fpdnjj`)JimnT|n axu]b`aurj9:;oi{}U{e}kciog,IdbcWyi%buzPaefpqg6789Usc2=0?0`?lht|Vzb|hbfnd-NeabXxj$etyQndeqvf5678Vrd~1<>>3a8mkusWyc{iagae.Ob`aYwk'dsxRokdrwa4567Wqey0?<12b9jjvrXx`zn`d`j/Lcg`Zvd&grSljkst`3456Xpfx7>>0=c:kmwqYwayogeck M`fg[ue)fq~Tmij|uc2345Yg{69832?m4ioqw[uowmecei"Cnde]sg+h|Vkoh~{m0123[}iu4;<5>n5fnrv\tlvbd`dn#@okd^r`*k~sWhnoxl?012\|jt;:>49o6gasu]smuckago$Aljk_qa-j}rXimnxyo>?01]{kw:5078h7d`|t^rjt`jnfl%FmijPpb,m|qYflmy~n=>?0^zlv94>6;h0ec}{_qksaioim&GjhiQc/l{pZgclzi<=>?_ymq8785k2ceyQiqgomkc(EhnoS}m!nyv\eabt}k:;<=Qwos>04;4d3`dxxR~fpdnjj`)JimnT|n axu]b`aurj9:;oi{}U{e}kciog,IdbcWyi%buzPaefpqg6789Usc2;>3`8mkusWyc{iagae.Ob`aYwk'dsxRokdrwa4567Wqey080=b:kmwqYwayogeck M`fg[ue)fq~Tmij|uc2345Yg{6=2?l4ioqw[uowmecei"Cnde]sg+h|Vkoh~{m0123[}iu4>49n6gasu]smuckago$Aljk_qa-j}rXimnxyo>?01]{kw:?6;h0ec}{_qksaioim&GjhiQc/l{pZgclzi<=>?_ymq8<85m2ceyQiqgomkc(EhnoS}m!pb]avdhd`Vkoh=>?0^az8469:l1bb~zPphrfhlhb'DkohR~l.qa\fwgikaUjhi>?01]`}9766;o0ec}{_qksaioim&GjhiQc/r`[gtffjbTmij?012\g|:6:78n7d`|t^rjt`jnfl%FmijPpb,sgZduigicSljk0123[f;9:49i6gasu]smuckago$Aljk_qa-tfYezhdhdRokd1234Ze~48>5>h5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Ydq5;>2?k4ioqw[uowmecei"Cnde]sg+vdWkxjbnfPaef3456Xkp6::33g8mkusWyc{iagae.Ob`aYwk'zhSo|nnbj\eab789:Tot2=0?0f?lht|Vzb|hbfnd-NeabXxj${oRl}aoak[dbc89:;Snw320<1a>oi{}U{e}kciog,IdbcWyi%|nQmr`l`lZgcl9:;Pcx>10;4b3`dxxR~fpdnjj`)JimnT|n c^`qekeoWhno<=>?_b{?6085m2ceyQiqgomkc(EhnoS}m!pb]avdhd`Vkoh=>?0^az8709:l1bb~zPphrfhlhb'DkohR~l.qa\fwgikaUjhi>?01]`}9406;o0ec}{_qksaioim&GjhiQc/r`[gtffjbTmij?012\g|:5078n7d`|t^rjt`jnfl%FmijPpb,sgZduigicSljk0123[f;:049h6gasu]smuckago$Aljk_qa-tfYezhdhdRokd1234Ze~4;49i6gasu]smuckago$Aljk_qa-tfYezhdhdRokd1234Ze~4::5>i5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Ydq595>i5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Ydq5>5>i5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Ydq5?5>i5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Ydq5<5>i5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Ydq5=5>i5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Ydq525>i5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Ydq535>k5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Yk}}6:<32?0e?lht|Vzb|hbfnd-NeabXxj${oRl}aoak[dbc89:;Sa{{<01=6c=nfz~T|d~jlhlf+HgclVzh"}mPbscmgmYflm:;<=Qcuu>20;4a3`dxxR~fpdnjj`)JimnT|n c^`qekeoWhno<=>?_mww8439:o1bb~zPphrfhlhb'DkohR~l.qa\fwgikaUjhi>?01]oqq:6>78m7d`|t^rjt`jnfl%FmijPpb,sgZduigicSljk0123[iss48=5>k5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Yk}}6:4316;4a3`dxxR~fpdnjj`)JimnT|n c^`qekeoWhno<=>?_mww8759:o1bb~zPphrfhlhb'DkohR~l.qa\fwgikaUjhi>?01]oqq:5<78m7d`|t^rjt`jnfl%FmijPpb,sgZduigicSljk0123[iss4;?5>k5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Yk}}69:31:7`Pltv?7585n2ceyQiqgomkc(EhnoS}m!pb]avdhd`Vkoh=>?0^nvp9566;o0ec}{_qksaioim&GjhiQc/r`[gtffjbTmij?012\hpr;;78n7d`|t^rjt`jnfl%FmijPpb,sgZduigicSljk0123[iss4=49i6gasu]smuckago$Aljk_qa-tfYezhdhdRokd1234Zjr|5?5>h5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Yk}}6=2?k4ioqw[uowmecei"Cnde]sg+vdWkxjbnfPaef3456Xd|~7;30?0e?lht|Vzb|hbfnd-NeabXxj${oRl}aoak[dbc89:;Sua}<03=6c=nfz~T|d~jlhlf+HgclVzh"}mPbscmgmYflm:;<=Qwos>26;4a3`dxxR~fpdnjj`)JimnT|n c^`qekeoWhno<=>?_ymq8459:o1bb~zPphrfhlhb'DkohR~l.qa\fwgikaUjhi>?01]{kw:6<78m7d`|t^rjt`jnfl%FmijPpb,sgZduigicSljk0123[}iu48?5>k5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Yg{6::38?0e?lht|Vzb|hbfnd-NeabXxj${oRl}aoak[dbc89:;Sua}<0;=6c=nfz~T|d~jlhlf+HgclVzh"}mPbscmgmYflm:;<=Qwos>14;4a3`dxxR~fpdnjj`)JimnT|n c^`qekeoWhno<=>?_ymq8779:o1bb~zPphrfhlhb'DkohR~l.qa\fwgikaUjhi>?01]{kw:5:78m7d`|t^rjt`jnfl%FmijPpb,sgZduigicSljk0123[}iu4;95>k5fnrv\tlvbd`dn#@okd^r`*ueXj{keoeQnde2345Yg{69831<;4a3`dxxR~fpdnjj`)JimnT|n c^`qekeoWhno<=>?_ymq87?9:l1bb~zPphrfhlhb'DkohR~l.qa\fwgikaUjhi>?01]{kw:56;l0ec}{_qksaioim&GjhiQc/r`[gtffjbTmij?012\|jt;;949j6gasu]smuckago$Aljk_qa-tfYezhdhdRokd1234Z~hz59:2?k4ioqw[uowmecei"Cnde]sg+vdWkxjbnfPaef3456Xpfx7?33g8mkusWyc{iagae.Ob`aYwk'zhSo|nnbj\eab789:Ttb|37?0f?lht|Vzb|hbfnd-NeabXxj${oRl}aoak[dbc89:;Sua}<9<1a>oi{}U{e}kciog,IdbcWyi%|nQmr`l`lZgcl9:;3:4`f:kmwqYwayogeck M`fg[sgcl{Uhu1?:>0d8mkusWyc{iagae.Ob`aYqimnySnw317<2b>oi{}U{e}kciog,IdbcWkohQly=34:4`68o0ec}{_qksaioim&GjhiQyaefq[f;97;m7d`|t^rjt`jnfl%FmijPv`fgvZe~4;:5=k5fnrv\tlvbd`dn#@okd^tb`atXkp69=3?i;hlppZvnxlfbbh!Baef\rdbczVir0?<11g9jjvrXx`zn`d`j/Lcg`ZpflmxTot2=3?3e?lht|Vzb|hbfnd-NeabX~hno~Rmv<36=5c=nfz~T|d~jlhlf+HgclV|jhi|Pcx>11;7a3`dxxR~fpdnjj`)JimnTzljkr^az87099o1bb~zPphrfhlhb'DkohRxndep\g|:5?7;m7d`|t^rjt`jnfl%FmijPv`fgvZe~4;25=k5fnrv\tlvbd`dn#@okd^tb`atXkp6953?j;hlppZvnxlfbbh!Baef\rdbczVir0?0>f:kmwqYwayogeck M`fg[sgcl{Uhu1=?>0g8mkusWyc{iagae.Ob`aYqimnySnw33?3f?lht|Vzb|hbfnd-NeabX~hno~Rmv<5<2a>oi{}U{e}kciog,IdbcWkohQly=7=5`=nfz~T|d~jlhlf+HgclV|jhi|Pcx>5:4c4ioqw[uowmecei"Cnde]ueabuWe0^QT476328mkusWyc{iagae.Ob`aYqimnySa{{<0;=5c=nfz~T|d~jlhlf+HgclV|jhi|Pltv?5;473`dxxR~fpdnjj`)JimnTzljkr^nvp9476;:0ec}{_qksaioim&GjhiQyaefq[iss4;;5>=5fnrv\tlvbd`dn#@okd^tb`atXd|~7>?0=0:kmwqYwayogeck M`fg[sgcl{Ugyy2=3?03?lht|Vzb|hbfnd-NeabX~hno~Rbzt=07:76328mkusWyc{iagae.Ob`aYqimnySa{{<3;=5c=nfz~T|d~jlhlf+HgclV|jhi|Pltv?6;473`dxxR~fpdnjj`)JimnTzljkr^nvp9576;:0ec}{_qksaioim&GjhiQyaefq[iss4:;5=k5fnrv\tlvbd`dn#@okd^tb`atXd|~7?3?i;hlppZvnxlfbbh!Baef\rdbczVf~x1:11g9jjvrXx`zn`d`j/Lcg`ZpflmxT`xz35?3e?lht|Vzb|hbfnd-NeabX~hno~Rbzt=4=5c=nfz~T|d~jlhlf+HgclV|jhi|Pltv?3;7a3`dxxR~fpdnjj`)JimnTzljkr^nvp9>99o1bb~zPphrfhlhb'DkohRxndep\hpr;17;m7d`|t^rjt`jnfl%FmijPv`fgvZ~hz5:5>=5fnrv\tlvbd`dn#@okd^tb`atXpfx7==0=0:kmwqYwayogeck M`fg[sgcl{Usc2>1?03?lht|Vzb|hbfnd-NeabX~hno~Rv`r=31:76328mkusWyc{iagae.Ob`aYqimnySua}<05=65=nfz~T|d~jlhlf+HgclV|jhi|Pxnp?5=8582ceyQiqgomkc(EhnoS{okds]{kw:617;m7d`|t^rjt`jnfl%FmijPv`fgvZ~hz5;5>=5fnrv\tlvbd`dn#@okd^tb`atXpfx7>=0=0:kmwqYwayogeck M`fg[sgcl{Usc2=1?03?lht|Vzb|hbfnd-NeabX~hno~Rv`r=01:76328mkusWyc{iagae.Ob`aYqimnySua}<35=65=nfz~T|d~jlhlf+HgclV|jhi|Pxnp?6=8582ceyQiqgomkc(EhnoS{okds]{kw:517;m7d`|t^rjt`jnfl%FmijPv`fgvZ~hz585>=5fnrv\tlvbd`dn#@okd^tb`atXpfx7?=0=0:kmwqYwayogeck M`fg[sgcl{Usc2<1?3e?lht|Vzb|hbfnd-NeabX~hno~Rv`r=1=5c=nfz~T|d~jlhlf+HgclV|jhi|Pxnp?0;7a3`dxxR~fpdnjj`)JimnTzljkr^zlv9399o1bb~zPphrfhlhb'DkohRxndep\|jt;>7;m7d`|t^rjt`jnfl%FmijPv`fgvZ~hz5=5=k5fnrv\tlvbd`dn#@okd^tb`atXpfx743?i;hlppZvnxlfbbh!Baef\rdbczVrd~171229jjvrXx`zn`d`j/Lov|ZOCWz~jkh fml3244403`dxxR~fpdnjj`)Je|rTEIQ|t`ef[lkjWge<=>?289jjvrXx`zn`d`j/Lov|ZOCWz~jkhQfml]mkq67899<>i5fnrv\tlvbd`dn#@czx^KG[vrfolUba`Qaou234550WZ];>i5fnrv\tlvbd`dn#@czx^KG[vrfolUba`Qaou234550WZ]:>45fnrv\tlvbd`dn#@czx^KG[vrfolUba`Qaou234500:>1bb~zPphrfhlhb'Dg~tRGK_rvbc`YnedUecy>?000a?lht|Vzb|hbfnd-Nip~XAMUxxlij_hon[kis89::S^Y?309jjvrXx`zn`d`j/Lov|ZKBEVymjk!ey]qavsk|Vg~t=>?202277=nfz~T|d~jlhlf+HkrpVGNAR}{afg-a}YumzgxRczx12364669:>0ec}{_qksaioim&GfyuQBEL]ppdab&lrT~h}zlu]nq}678;;;=Rh:309jjvrXx`zn`d`j/Lov|ZKBEVymjk!ey]qavsk|Vg~t=>?203374=nfz~T|d~jlhlf+HkrpVGNAR}{afg-a}YumzgxRczx1236476;;1bb~zPphrfhlhb'Dg~tRCJM^qwebc)mqUyi~{ct^ov|567:8;:=>:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;1^d674=nfz~T|d~jlhlf+HkrpVGNAR}{afg-a}YumzgxRczx1236446;;1bb~zPphrfhlhb'Dg~tRCJM^qwebc)mqUyi~{ct^ov|567:88:=>:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;:=>:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;6;;1bb~zPphrfhlhb'Dg~tRCJM^qwebc)mqUyi~{ct^ov|567:82:=>:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;:4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;<4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;<4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;??>339jjvrXx`zn`d`j/Lov|ZKBEVymjk!ey]qavsk|Vg~t=>?2332562?<5fnrv\tlvbd`dn#@czx^OFIZusino%iuQ}erwopZkrp9:;>??=329jjvrXx`zn`d`j/Lov|ZKBEVymjk!ey]qavsk|Vg~t=>?233\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz34545:8997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~78989>=233\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz34545;8997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~78989?=223\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz34545<8997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~789898=253\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz34545=8997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~789899=243\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz34545>8997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~78989:=273\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz34545?8997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~78989;=263\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz3454508997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~789894=293\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz3454518997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~789895=283\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz3454488997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~78988<=313\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz3454498997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~78988==303\b0563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz34544:8997d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~78988>=333\b0573`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz34544;:;0ec}{_qksaioim&GfyuQBEL]ppdab&lrT~h}zlu]nq}678;98=>=4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;oi{}U{e}kciog,IhsWDOFS~zngd,f|Ztb{|fS`{w012104563`dxxR~fpdnjj`)Je|rTAHCPsucda+cW{oxyazPmtz3454398987d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~7898?=Rh:319jjvrXx`zn`d`j/Lov|ZKBEVymjk!ey]qavsk|Vg~t=>?24305>oi{}U{e}kciog,IhsWDOFS~zngd,f|Ztb{|fS`{w01211474;2ceyQiqgomkc(EdsS@KB_rvbc`(bpVxnxb{_lw{4565=8Um9>>4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;309jjvrXx`zn`d`j/Lov|ZKBEVymjk!ey]qavsk|Vg~t=>?273276=nfz~T|d~jlhlf+HkrpVGNAR}{afg-a}YumzgxRczx123637Xn<9;7d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~7898<=>?4ioqw[uowmecei"Cbuy]NAHYt|hmn"hvPrdqvhqYj}q:;1218mkusWyc{iagae.Onq}YJMDUxxlij.dz\v`urd}Ufyu>?0352[c3482ceyQiqgomkc(EdsS@KB_rvbc`(bpVxnxb{_lw{4565089:7d`|t^rjt`jnfl%FaxvPMDO\wqg`m'osSk|umv\ip~78983=<=<;hlppZvnxlfbbh!Bmtz\I@KX{}kli#kw_sgpqirXe|r;<=<71^d675=nfz~T|d~jlhlf+HkrpVGNAR}{afg-a}YumzgxRczx1236<7492ceyQiqgomkc(EdsS@KB_rvbc`(bpVxnxb{_lw{456518;8?6gasu]smuckago$A`{w_LGN[vrfol$ntR|jstnw[hs89:95103f?lht|Vzb|hbfnd-Nip~Xxj$hy|>1032g>oi{}U{e}kciog,IhsWyi%ox|}133g?lht|Vzb|hbfnd-Nip~Xxj$hy|>203g?lht|Vzb|hbfnd-Nip~Xxj$hy|>303f?lht|Vzb|hbfnd-Nip~Xxj$hy|>3032`>oi{}U{e}kciog,IhsWyi%ox|}1532a>oi{}U{e}kciog,IhsWyi%ox|}15325a=nfz~T|d~jlhlf+HkrpVzh"n{}r0725`=nfz~T|d~jlhlf+HkrpVzh"n{}r07254bd:kmwqYwayogeck Mlw{[ue)k|xy>5?>e:kmwqYwayogeck Mlw{[ue)k|xy>5?>1e9jjvrXx`zn`d`j/Lov|Zvd&jy~?7>1d9jjvrXx`zn`d`j/Lov|Zvd&jy~?7>10f8mkusWyc{iagae.Onq}Ywk'i~~=?10g8mkusWyc{iagae.Onq}Ywk'i~~=?103g?lht|Vzb|hbfnd-Nip~Xxj$hy|<103f?lht|Vzb|hbfnd-Nip~Xxj$hy|<1032`>oi{}U{e}kciog,IhsWyi%ox|}3332a>oi{}U{e}kciog,IhsWyi%ox|}33325f=nfz~T|d~jlhlf+HkrpVzh"n{}r212`>oi{}U{e}kciog,IhsWyi%ox|}3232g>oi{}U{e}kciog,IhsWyi%ox|}403g?lht|Vzb|hbfnd-Nip~Xxj$hy|;103f?lht|Vzb|hbfnd-Nip~Xxj$hy|;1^D2a>oi{}U{e}kciog,IhsWyi%ox|}40]D5f=nfz~T|d~jlhlf+HkrpVzh"n{}r432`>oi{}U{e}kciog,IhsWyi%ox|}5032a>oi{}U{e}kciog,IhsWyi%ox|}50]E5`=nfz~T|d~jlhlf+HkrpVzh"n{}r43\C4eoi{}U{e}kciog,IhsWyi%ox|}7032g>oi{}U{e}kciog,IhsWyi%ox|}803g?lht|Vzb|hbfnd-Nip~Xxj$hy|7103`?lht|Vzb|hbfnd-Nip~Xxj$hy|610f8mkusWyc{iagae.Onq}Ywk'i~~7>1348mkusWyc{iagae.Onq}Yumzgx>8Pmtz3457688837d`|t^rjt`jnfl%FaxvPrdqvhq51Wds<=>>113\B7>;?=f:kmwqYwayogeck Mrwa[wctm}Uoiaov_`fgwpd789:Tot2=>238mkusWyc{iagae.OpqgYumzoSikcax]b`aurj9:;oi{}U{e}kciog,SGYt|hmn"io{a^315`=nfz~T|d~jlhlf+RDX{}kli#jnt`]274c??j;hlppZvnxlfbbh!XB^qwebc)lh~jS?=>e:kmwqYwayogeck WC]ppdab&mkmR<;1d9jjvrXx`zn`d`j/V@\wqg`m'njxlQ=50g8mkusWyc{iagae.UA[vrfol$omyoP273f?lht|Vzb|hbfnd-TFZusino%hlzn_352a>oi{}U{e}kciog,SGYt|hmn"io{a^0;5`=nfz~T|d~jlhlf+RDX{}kli#jnt`]1=4b6l2ceyQiqgomkc(_KUxxlij.ecweZ?592ceyQiqgomkc(_KUxxlij.sgd[rvszV:9?6gasu]smuckago$[OQ|t`ef*wc`W~z~R>P1338mkusWyc{iagae.UA[vrfol$yijQxpup\575oi{}U{e}kciog,SGYt|hmn"kh_vrwvZ5X9;;0ec}{_qksaioim&]IS~zngd,qabYpx}xT8?0338mkusWyc{iagae.UA[vrfolUihRa}01235733`dxxR~fpdnjj`)PJVymjkPwsgd[rcXg{:;<=Qfnw0b?lht|Vzb|hbfnd-TFZusinoT{kh_vg\kw6789Ubb{?>a:kmwqYwayogeck bbw\big`{Voz=45fnrv\tlvbd`dn#omz_nr\e9699h1bb~zPphrfhlhb'ki~Sb~Pa=33:4g1?3b?lht|Vzb|hbfnd-agpYhxVk7=?0>a:kmwqYwayogeck bbw\kuYf4895=l5fnrv\tlvbd`dn#omz_nr\e97368k0ec}{_qksaioim&hhyRa_`>21;7f3`dxxR~fpdnjj`)ek|Ud|Ro317<2e>oi{}U{e}kciog,ffsXgyUj0<911`9jjvrXx`zn`d`j/cav[jvXi5;32oi{}U{e}kciog,ffsXgyUj0??11`9jjvrXx`zn`d`j/cav[jvXi58920c8mkusWyc{iagae.``qZiwWh69;3?n;hlppZvnxlfbbh!mct]ltZg;:14:m6gasu]smuckago$nn{Poq]b87?9901bb~zPphrfhlhb'ki~Sb~Pa=0=5d=nfz~T|d~jlhlf+gerWfzTm1=?>0c8mkusWyc{iagae.``qZiwWh68=3?6;hlppZvnxlfbbh!mct]ltZg;;7;27d`|t^rjt`jnfl%ioxQ`p^c?0;7>3`dxxR~fpdnjj`)ek|Ud|Ro35?3:?lht|Vzb|hbfnd-agpYhxVk7:3?6;hlppZvnxlfbbh!mct]ltZg;?7;27d`|t^rjt`jnfl%ioxQ`p^c?<;7>3`dxxR~fpdnjj`)ek|Ud|Ro39?3;?lht|Vzb|hbfnd-agpYhxVkT<<64ioqw[uowmecei"llu^ms[dY6901bb~zPphrfhlhb'ki~Sb~Pa^335<=nfz~T|d~jlhlf+gerWfzTmR?>189jjvrXx`zn`d`j/cav[jvXiV;9=45fnrv\tlvbd`dn#omz_nr\eZ74901bb~zPphrfhlhb'ki~Sb~Pa^375<=nfz~T|d~jlhlf+gerWfzTmR?:189jjvrXx`zn`d`j/cav[jvXiV;==45fnrv\tlvbd`dn#omz_nr\eZ70901bb~zPphrfhlhb'ki~Sb~Pa^3;5<=nfz~T|d~jlhlf+gerWfzTmR?6199jjvrXx`zn`d`j/cav[jvXiV8:56gasu]smuckago$nn{Poq]b[76612ceyQiqgomkc(jjTc}Qn_332=>oi{}U{e}kciog,ffsXgyUjS?<>9:kmwqYwayogeck bbw\kuYfW;9:56gasu]smuckago$nn{Poq]b[72612ceyQiqgomkc(jjTc}Qn_372=>oi{}U{e}kciog,ffsXgyUjS?8>9:kmwqYwayogeck bbw\kuYfW;=:56gasu]smuckago$nn{Poq]b[7>612ceyQiqgomkc(jjTc}Qn_3;2<>oi{}U{e}kciog,ffsXgyUjS>?6;hlppZvnxlfbbh!mct]ltZgX;9;27d`|t^rjt`jnfl%ioxQ`p^c\747?3`dxxR~fpdnjj`)ek|Ud|RoP40:8mkusWyc{iagae.``qZiwWhU>=55fnrv\tlvbd`dn#omz_nr\eZ0602ceyQiqgomkc(jjTc}Qn_63;?lht|Vzb|hbfnd-agpYhxVkT4<64ioqw[uowmecei"llu^ms[dY>901bb~zPphrfhlhb'ki~Sb~Pb=2=5d=nfz~T|d~jlhlf+gerWfzTn1??>0c8mkusWyc{iagae.``qZiwWk6:=3?n;hlppZvnxlfbbh!mct]ltZd;9;4:m6gasu]smuckago$nn{Poq]a84599h1bb~zPphrfhlhb'ki~Sb~Pb=37:4g5?3b?lht|Vzb|hbfnd-agpYhxVh7=;0>a:kmwqYwayogeck bbw\kuYe48=5=l5fnrv\tlvbd`dn#omz_nr\f97?68k0ec}{_qksaioim&hhyRa_c>2=;7>3`dxxR~fpdnjj`)ek|Ud|Rl31?3b?lht|Vzb|hbfnd-agpYhxVh7>=0>a:kmwqYwayogeck bbw\kuYe4;;5=l5fnrv\tlvbd`dn#omz_nr\f94568k0ec}{_qksaioim&hhyRa_c>17;7f3`dxxR~fpdnjj`)ek|Ud|Rl325<2e>oi{}U{e}kciog,ffsXgyUi0?;11`9jjvrXx`zn`d`j/cav[jvXj58=23`dxxR~fpdnjj`)ek|Ud|Rl34?3:?lht|Vzb|hbfnd-agpYhxVh793?6;hlppZvnxlfbbh!mct]ltZd;>7;27d`|t^rjt`jnfl%ioxQ`p^`?3;7>3`dxxR~fpdnjj`)ek|Ud|Rl38?3:?lht|Vzb|hbfnd-agpYhxVh753?7;hlppZvnxlfbbh!mct]ltZdX8820ec}{_qksaioim&hhyRa_c]25<=nfz~T|d~jlhlf+gerWfzTnR??189jjvrXx`zn`d`j/cav[jvXjV;:=45fnrv\tlvbd`dn#omz_nr\fZ75901bb~zPphrfhlhb'ki~Sb~Pb^305<=nfz~T|d~jlhlf+gerWfzTnR?;189jjvrXx`zn`d`j/cav[jvXjV;>=45fnrv\tlvbd`dn#omz_nr\fZ71901bb~zPphrfhlhb'ki~Sb~Pb^345<=nfz~T|d~jlhlf+gerWfzTnR?7189jjvrXx`zn`d`j/cav[jvXjV;2=55fnrv\tlvbd`dn#omz_nr\fZ4612ceyQiqgomkc(jjTc}Qm_322=>oi{}U{e}kciog,ffsXgyUiS??>9:kmwqYwayogeck bbw\kuYeW;8:56gasu]smuckago$nn{Poq]a[75612ceyQiqgomkc(jjTc}Qm_362=>oi{}U{e}kciog,ffsXgyUiS?;>9:kmwqYwayogeck bbw\kuYeW;<:56gasu]smuckago$nn{Poq]a[71612ceyQiqgomkc(jjTc}Qm_3:2=>oi{}U{e}kciog,ffsXgyUiS?7>8:kmwqYwayogeck bbw\kuYeW:;27d`|t^rjt`jnfl%ioxQ`p^`\757>3`dxxR~fpdnjj`)ek|Ud|RlP303;?lht|Vzb|hbfnd-agpYhxVhT8<64ioqw[uowmecei"llu^ms[gY2911bb~zPphrfhlhb'ki~Sb~Pb^42<>oi{}U{e}kciog,ffsXgyUiS:?7;hlppZvnxlfbbh!mct]ltZdX0820ec}{_qksaioim&hhyRa_c]:52=nfz~T|d~jlhlf+gtffjbToh?j;hlppZvnxlfbbh!mr`l`lZebW{y|bz>f:kmwqYwayogeck bscmgmYdmVxxx}a{1018mkusWyc{iagae.aooZ46i2ceyQiqgomkc(keaT>7d`|t^rjt`jnfl%h|xQ}su3g?lht|Vzb|hbfnd-`tpYu{}Ujbi>?013f?lht|Vzb|hbfnd-`tpYu{}Ujbi>?01310>oi{}U{e}kciog,gqtkWecei~Qnlt]lt7Ytzj837d`|t^rjt`jnfl%hxbPlhlfwZgk}VycekzPaskwl7>oi{}U{e}kciog,gqtkWecei~Qeulr16>oi{}U{e}kciog,gqtkWecei~Qeulr\hjh`:?1bb~zPphrfhlhb'j~y`Rbfndq\wmgj|;Ux~n}jl338mkusWyc{iagae.awviYkagoxSza}d3]fj4`Taxv?012?4;76m2ceyQiqgomkc(lh~j8Rczx12349799o1bb~zPphrfhlhb'mkm9Qbuy2345:668;n7d`|t^rjt`jnfl%omyo;_lw{45674;4:j6gasu]smuckago$hlzn4^ov|5678585=0>1d9jjvrXx`zn`d`j/ecwe1Yj}q:;<=2;>0d8mkusWyc{iagae.fbpd2Xe|r;<=>34?32b>oi{}U{e}kciog,`drf=V:Taxv?0102<4`Pmtz34545;VL9=6gasu]smuckago$hlzn5^2\ip~78989?RI>f:kmwqYwayogeck d`vb1Z6Xe|r;<=<=70d8mkusWyc{iagae.fbpd3X8Vg~t=>?2232a>oi{}U{e}kciog,`drf=V:Taxv?010765=nfz~T|d~jlhlf+agsi?5fnrv\tlvbd`dn#io{a4]24Zkrp9:;>?>PG328mkusWyc{iagae.fbpd3X99Ufyu>?030461=nfz~T|d~jlhlf+agsiX[^:986gasu]smuckago$hlzn5^33[hs89:9?5Q\W003?lht|Vzb|hbfnd-geqg2W8:Taxv?010504`_lw{4565:9897d`|t^rjt`jnfl%omyo:_03\ip~78989=21]D61=nfz~T|d~jlhlf+agsiX[^:986gasu]smuckago$hlzn5^32[hs89:9?5Q\W003?lht|Vzb|hbfnd-geqg2W8;Taxv?010504`=21]D61=nfz~T|d~jlhlf+agsiRczx12366>X[^:986gasu]smuckago$hlzn5^31[hs89:9?5Q\W003?lht|Vzb|hbfnd-geqg2W88Taxv?010504`=21]D61=nfz~T|d~jlhlf+agsiX[^:986gasu]smuckago$hlzn5^30[hs89:9?5Q\W003?lht|Vzb|hbfnd-geqg2W89Taxv?010504`Qbuy23471582ceyQiqgomkc(lh~j9R?;_lw{4565:9897d`|t^rjt`jnfl%omyo:_06\ip~78989=21]D61=nfz~T|d~jlhlf+agsiX[^:986gasu]smuckago$hlzn5^37[hs89:9?5Q\W003?lht|Vzb|hbfnd-geqg2W8>Taxv?010504`=<=;hlppZvnxlfbbh!kauc6[40Xe|r;<=<=0^D16>oi{}U{e}kciog,`drf=V;=S`{w012165Y@:91bb~zPphrfhlhb'mkm8Q>6^ov|567::2986gasu]smuckago$hlzn5^35[hs89:9?5Q\W103?lht|Vzb|hbfnd-geqg2W895fnrv\tlvbd`dn#io{a4]22Zkrp9:;>;:PSV314>oi{}U{e}kciog,`drf=V;S<9Pmtz345440;:0ec}{_qksaioim&njxl;P16]nq}678;95fnrv\tlvbd`dn#io{a4]23Zkrp9:;>;:PSV210>oi{}U{e}kciog,`drf=V;X[^;9:6gasu]smuckago$hlzn5^3;[hs89:9?5Q\W0]E63=nfz~T|d~jlhlf+agsiX[^;TK?>4ioqw[uowmecei"jnt`7\5=Yj}q:;?2603?lht|Vzb|hbfnd-geqg2W83Taxv?01014769^ov|567:?>986gasu]smuckago$hlzn5^3:[hs89:9:9Q\W107?lht|Vzb|hbfnd-geqg2W83Taxv?01050ZUP98l0ec}{_qksaioim&njxl;P1^ov|567:;9:j6gasu]smuckago$hlzn5^3\ip~78989;9?031;[VQ7:=1bb~zPphrfhlhb'mkm8Q=0^ov|567::2T_Z?=6:kmwqYwayogeck d`vb1Z47Wds<=>=39]PS4YA:?1bb~zPphrfhlhb'mkm8Q=0^ov|567::2T_Z?PG328mkusWyc{iagae.fbpd3X:9Ufyu>?03475c=nfz~T|d~jlhlf+agsiS??Pmtz345458;:0ec}{_qksaioim&njxl;P20]nq}678;93>=5fnrv\tlvbd`dn#io{a4]15Zkrp9:;>;:=4:kmwqYwayogeck d`vb1Z46Wds<=>=65]PS5433`dxxR~fpdnjj`)ci}k>S??Pmtz345414ioqw[uowmecei"jnt`7\67Yj}q:;?22:14>oi{}U{e}kciog,`drf=V89S`{w012121433`dxxR~fpdnjj`)ci}k>S?=<=;hlppZvnxlfbbh!kauc6[72Xe|r;<=<=0^D16>oi{}U{e}kciog,`drf=V8?S`{w012165Y@:81bb~zPphrfhlhb'mkm8Q=4^ov|567:?>:>?5fnrv\tlvbd`dn#io{a4]10Zkrp9:;>;:>1308mkusWyc{iagae.fbpd3X:=Ufyu>?034757433`dxxR~fpdnjj`)ci}k>S?:Pmtz34541<8Um9?>4ioqw[uowmecei"jnt`7\60Yj}q:;?232\B748Qbuy234747WN8:7d`|t^rjt`jnfl%omyo:_37\ip~7898=8<<=;hlppZvnxlfbbh!kauc6[73Xe|r;<=<940316>oi{}U{e}kciog,`drf=V8>S`{w01212175:=1bb~zPphrfhlhb'mkm8Q=5^ov|567:?>:Sk;=0:kmwqYwayogeck d`vb1Z41Wds<=>=2101?lht|Vzb|hbfnd-geqg2W;<5fnrv\tlvbd`dn#io{a4]12Zkrp9:;>;:>239jjvrXx`zn`d`j/ecwe0Y5>Vg~t=>?2762574;Qbuy2347039;8?7d`|t^rjt`jnfl%omyo:_34\ip~7898=8Ufyu>?030367=nfz~T|d~jlhlf+agsi;hlppZvnxlfbbh!kauc6[71Xe|r;<=<94001?lht|Vzb|hbfnd-geqg2W;=Taxv?01050475:2ceyQiqgomkc(lh~j9R<8_lw{4565>=;9>95fnrv\tlvbd`dn#io{a4]13Zkrp9:;>;:>_g714>oi{}U{e}kciog,`drf=V83S`{w012165453`dxxR~fpdnjj`)ci}k>S?6Pmtz345458VL9>6gasu]smuckago$hlzn5^0;[hs89:9>=QH209jjvrXx`zn`d`j/ecwe0Y50Vg~t=>?276267=nfz~T|d~jlhlf+agsiXe|r;<=<940]e1764Qbuy234747:;1bb~zPphrfhlhb'mkm8Q=9^ov|567:;:TJ?<4ioqw[uowmecei"jnt`7\6S?7Pmtz34541<8;9>6gasu]smuckago$hlzn5^0:[hs89:9:9?=259jjvrXx`zn`d`j/ecwe0Y51Vg~t=>?2762[c36n2ceyQiqgomkc(lh~j9R=5fnrv\tlvbd`dn#io{a4]04Zkrp9:;>?>=2:kmwqYwayogeck d`vb1Z57Wds<=>=21]E67=nfz~T|d~jlhlf+agsioi{}U{e}kciog,`drf=V9:S`{w0121217Xn<8=7d`|t^rjt`jnfl%omyo:_23\ip~7898=8RHPSV213>oi{}U{e}kciog,`drf=V9:S`{w012121YAWZ];=?94ioqw[uowmecei"jnt`7\74Yj}q:;_lw{4565>=UMS^Y?_g72b>oi{}U{e}kciog,`drf=V9Taxv?010174`?=>f:kmwqYwayogeck d`vb1Z3Xe|r;<=<=70g8mkusWyc{iagae.fbpd3X=Vg~t=>?253e?lht|Vzb|hbfnd-geqg2W?Ufyu>?03005c=nfz~T|d~jlhlf+agsiS;Qbuy23472592ceyQiqgomkc(lh~j9R9Paef3456;9949=6gasu]smuckago$hlzn5^5\eab789:7=<0=1:kmwqYwayogeck d`vb1Z1Ximn;<=>313<15>oi{}U{e}kciog,`drf=V=Tmij?012?568592ceyQiqgomkc(lh~j9R9Paef3456;9=49=6gasu]smuckago$hlzn5^5\eab789:7=80=1:kmwqYwayogeck d`vb1Z1Ximn;<=>317<15>oi{}U{e}kciog,`drf=V=Tmij?012?528592ceyQiqgomkc(lh~j9R9Paef3456;9149=6gasu]smuckago$hlzn5^5\eab789:7=40=1:kmwqYwayogeck d`vb1Z1Ximn;<=>321<15>oi{}U{e}kciog,`drf=V=Tmij?012?648592ceyQiqgomkc(lh~j9R9Paef3456;:;49=6gasu]smuckago$hlzn5^5\eab789:7>>0=1:kmwqYwayogeck d`vb1Z1Ximn;<=>325<15>oi{}U{e}kciog,`drf=V=Tmij?012?608592ceyQiqgomkc(lh~j9R9Paef3456;:?49=6gasu]smuckago$hlzn5^5\eab789:7>:0=1:kmwqYwayogeck d`vb1Z1Ximn;<=>329<15>oi{}U{e}kciog,`drf=V=Tmij?012?6<8582ceyQiqgomkc(lh~j9R9Paef3456;:78:7d`|t^rjt`jnfl%omyo:_6]b`a678968<3<>;hlppZvnxlfbbh!kauc6[2Yflm:;<=2<1?03?lht|Vzb|hbfnd-geqg2W>Ujhi>?01>0:76328mkusWyc{iagae.fbpd3X?Vkoh=>?0=:=65=nfz~T|d~jlhlf+agsi=<>;hlppZvnxlfbbh!kauc6[=Yj}q:;?0303[B7a3`dxxR~fpdnjj`)ci}k>S5Qbuy23475?9o1bb~zPphrfhlhb'mkm8Q7_lw{4565>=887d`|t^rjt`jnfl%omyo:_9]nq}678;Wds<=>=2102?lht|Vzb|hbfnd-geqg2W0Ufyu>?0303[C463`dxxR~fpdnjj`)ci}k>S4Qbuy234747WN887d`|t^rjt`jnfl%omyo:_8]nq}678;93S^Y?229jjvrXx`zn`d`j/ecwe0Y>Wds<=>=39]PS47a3`dxxR~fpdnjj`)ci}k>S4Qbuy2347039l1bb~zPphrfhlhb'mkm8Q6_lw{4565?8k0ec}{_qksaioim&nfi`Qme=2=567f3`dxxR~fpdnjj`)celgTnh2?>332e>oi{}U{e}kciog,`hcjWko7<3=<1d9jjvrXx`zn`d`j/eofiZdb4848:R]X00c8mkusWyc{iagae.fnahYem5;58;?m;hlppZvnxlfbbh!kmdo\f`:66=<:=o5fnrv\tlvbd`dn#icjm^`f8483>;;o7d`|t^rjt`jnfl%oahcPbd>2:10Xn<;n7d`|t^rjt`jnfl%oahcPbd>1:6>X[^::m6gasu]smuckago$h`kb_cg?6;2>9k1bb~zPphrfhlhb'mgnaRlj<3<7=47e3`dxxR~fpdnjj`)celgTnh2=>5;15a=nfz~T|d~jlhlf+akbeVhn0?0;9^d65d=nfz~T|d~jlhlf+akbeVhn0>0>20c8mkusWyc{iagae.fnahYem595=8?n;hlppZvnxlfbbh!kmdo\f`:46;?::6gasu]smuckago$h`kb_egs52=nfz~T|d~jlhlf+akbeVnn|25;76k2ceyQiqgomkc(ldofSiazt=31:47d3`dxxR~fpdnjj`)celgThb{{<01=54e5?32g>oi{}U{e}kciog,`hcjWme~x1?9>03`?lht|Vzb|hbfnd-gi`kXlf0<9110a8mkusWyc{iagae.fnahYcg|~7=50>1b9jjvrXx`zn`d`j/eofiZbh}}6:53?>b:kmwqYwayogeck dlgn[air|5;5=11;76k2ceyQiqgomkc(ldofSiazt=05:47d3`dxxR~fpdnjj`)celgThb{{<35=54eoi{}U{e}kciog,`hcjWme~x1<110a8mkusWyc{iagae.fnahYcg|~7?=0>1b9jjvrXx`zn`d`j/eofiZbh}}68=3?>b:kmwqYwayogeck dlgn[air|595=oi{}U{e}kciog,`hcjWme~x1711078mkusWyc{iagae.fnahYbf8n0ec}{_qksaioim&nfi`Qjn^ov|567=8l0ec}{_qksaioim&nfi`Qjn^ov|567=VL:j6gasu]smuckago$h`kb_dl\ip~789?TK733a8mkusWyc{iagae.jgqZgk}Vl|hRoPey]3[dhc89:;4>Q>1g9jjvrXx`zn`d`j/ifv[djrWo}oSlQbel0e?lht|Vzb|hbfnd-k`pYfd|Um{iQn_lgn[5Yffm:;<=:?_RU36g=nfz~T|d~jlhlf+mbrWhf~Skyk_`]nahY7Whdo<=>?660a?lht|Vzb|hbfnd-k`pYfd|Um{iQn_lgn[5Yffm:;<=6<2b9jjvrXx`zn`d`j/ifv[djrWo}oSlQbel]3[dhc89:;4>?=d:kmwqYwayogeck hew\eisXn~nTmRcjm^2\ekb789:3?R?=d:kmwqYwayogeck hew\eisXn~nTmRcjm^2\ekb789:3?R<=f:kmwqYwayogeck hew\eisXn~nTmRcjm^2\ekb789:3?R]X00g8mkusWyc{iagae.jgqZgk}Vl|hRoPwc0f?lht|Vzb|hbfnd-k`pYfd|Um{iQn_v`\4Zgil9:;<9>PSV21e>oi{}U{e}kciog,lasXieTjzjPa^ua[5Yffm:;<=882`9jjvrXx`zn`d`j/ifv[djrWo}oSlQxb^2\ekb789:3??l4ioqw[uowmecei"fku^coqZ`plVkT{oQ?_`lg45670:;9o6gasu]smuckago$di{Pamw\brbXiV}iS=Qnne2345>4W88h7d`|t^rjt`jnfl%chxQnlt]esaYfW~hT?83c8mkusWyc{iagae.jgqZgk}Vl|hRlPey]3[dhc89:;4>?i;hlppZvnxlfbbh!gdt]bhpYamUiS`kb2c9jjvrXx`zn`d`j/ifv[djrWo}oSoQbel]3[dhc89:;>;;>o5fnrv\tlvbd`dn#ejz_`nv[cqcWkUfi`Q?_`lg4567>>8i7d`|t^rjt`jnfl%chxQnlt]esaYeWdofS=Qnne2345>59l1bb~zPphrfhlhb'an~Slbz_gug[gYpj;k0ec}{_qksaioim&boyRocu^dt`ZdXkU;Sl`k0123054f3`dxxR~fpdnjj`)ol|Uj`xQiwe]a[rdX8Vkeh=>?0751e>oi{}U{e}kciog,lasXieTjzjPb^ua[5Yffm:;<=6<2d9jjvrXx`zn`d`j/ifv[djrWo}oSoQxb^2\ekb789:3?R]X0048mkusWyc{iagae.knahYbf88o7d`|t^rjt`jnfl%bb~zPamw,IdbcWzfSljk0123[f;878n7d`|t^rjt`jnfl%bb~zPamw,IdbcWzfSljk0123[f;9949i6gasu]smuckago$ec}{_`nv+HgclVy~aRokd1234Ze~48;5>h5fnrv\tlvbd`dn#d`|t^coq*KflmUxy`Qnde2345Ydq5;92?k4ioqw[uowmecei"gasu]bhp)JimnTxcPaef3456Xkp6:?33g8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Tot2>7?0f?lht|Vzb|hbfnd-jjvrXie$Aljk_rwn[dbc89:;Snw319<1a>oi{}U{e}kciog,mkusWhf~#@okd^qviZgcl9:;Pcx>15;4b3`dxxR~fpdnjj`)nfz~Tma{ M`fg[vsjWhno<=>?_b{?6785m2ceyQiqgomkc(agySlbz/Lcg`ZureVkoh=>?0^az8759:l1bb~zPphrfhlhb'`dxxRocu.Ob`aYt}dUjhi>?01]`}9436;o0ec}{_qksaioim&ceyQnlt-NeabX{|gTmij?012\g|:5=78n7d`|t^rjt`jnfl%bb~zPamw,IdbcWzfSljk0123[f;:?49i6gasu]smuckago$ec}{_`nv+HgclVy~aRokd1234Ze~4;=5>h5fnrv\tlvbd`dn#d`|t^coq*KflmUxy`Qnde2345Ydq5832?k4ioqw[uowmecei"gasu]bhp)JimnTxcPaef3456Xkp69533?12d9jjvrXx`zn`d`j/hlppZgk}&GjhiQ|ul]b`a6789Uhu1==>3f8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Tot2<>3f8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Tot2;>3f8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Tot2:>3f8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Tot29>3f8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Tot28>3f8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Tot27>3f8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Tot26>3d8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:T`xz311<1b>oi{}U{e}kciog,mkusWhf~#@okd^qviZgcl9:;Pltv?5785n2ceyQiqgomkc(agySlbz/Lcg`ZureVkoh=>?0^nvp9746;l0ec}{_qksaioim&ceyQnlt-NeabX{|gTmij?012\hpr;9=49j6gasu]smuckago$ec}{_`nv+HgclVy~aRokd1234Zjr|5;>2?h4ioqw[uowmecei"gasu]bhp)JimnTxcPaef3456Xd|~7=;0=f:kmwqYwayogeck ioqw[djr'DkohR}zm^cg`5678Vf~x1?8>3d8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:T`xz319<1b>oi{}U{e}kciog,mkusWhf~#@okd^qviZgcl9:;Pltv?5;4a3`dxxR~fpdnjj`)nfz~Tma{ M`fg[vsjWhno<=>?_mww8769:o1bb~zPphrfhlhb'`dxxRocu.Ob`aYt}dUjhi>?01]oqq:5978m7d`|t^rjt`jnfl%bb~zPamw,IdbcWzfSljk0123[iss4;85>k5fnrv\tlvbd`dn#d`|t^coq*KflmUxy`Qnde2345Yk}}69?313;4a3`dxxR~fpdnjj`)nfz~Tma{ M`fg[vsjWhno<=>?_mww87>9:o1bb~zPphrfhlhb'`dxxRocu.Ob`aYt}dUjhi>?01]oqq:5178n7d`|t^rjt`jnfl%bb~zPamw,IdbcWzfSljk0123[iss4;49j6gasu]smuckago$ec}{_`nv+HgclVy~aRokd1234Zjr|59;2?h4ioqw[uowmecei"gasu]bhp)JimnTxcPaef3456Xd|~7?<0=f:kmwqYwayogeck ioqw[djr'DkohR}zm^cg`5678Vf~x1==>3g8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:T`xz33?0f?lht|Vzb|hbfnd-jjvrXie$Aljk_rwn[dbc89:;Sa{{<5<1a>oi{}U{e}kciog,mkusWhf~#@okd^qviZgcl9:;5:7cPltv?3;4b3`dxxR~fpdnjj`)nfz~Tma{ M`fg[vsjWhno<=>?_mww8=85m2ceyQiqgomkc(agySlbz/Lcg`ZureVkoh=>?0^nvp9?9:o1bb~zPphrfhlhb'`dxxRocu.Ob`aYt}dUjhi>?01]{kw:6878m7d`|t^rjt`jnfl%bb~zPamw,IdbcWzfSljk0123[}iu48;5>k5fnrv\tlvbd`dn#d`|t^coq*KflmUxy`Qnde2345Yg{6:>34?0e?lht|Vzb|hbfnd-jjvrXie$Aljk_rwn[dbc89:;Sua}<07=6c=nfz~T|d~jlhlf+lht|Vkgy"Cnde]pqhYflm:;<=Qwos>22;4a3`dxxR~fpdnjj`)nfz~Tma{ M`fg[vsjWhno<=>?_ymq8419:o1bb~zPphrfhlhb'`dxxRocu.Ob`aYt}dUjhi>?01]{kw:6078m7d`|t^rjt`jnfl%bb~zPamw,IdbcWzfSljk0123[}iu4835>h5fnrv\tlvbd`dn#d`|t^coq*KflmUxy`Qnde2345Yg{6:2?h4ioqw[uowmecei"gasu]bhp)JimnTxcPaef3456Xpfx7>=0=f:kmwqYwayogeck ioqw[djr'DkohR}zm^cg`5678Vrd~1<>>3d8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Ttb|323<1b>oi{}U{e}kciog,mkusWhf~#@okd^qviZgcl9:;Pxnp?6185n2ceyQiqgomkc(agySlbz/Lcg`ZureVkoh=>?0^zlv9426;l0ec}{_qksaioim&ceyQnlt-NeabX{|gTmij?012\|jt;:?49j6gasu]smuckago$ec}{_`nv+HgclVy~aRokd1234Z~hz58<2?h4ioqw[uowmecei"gasu]bhp)JimnTxcPaef3456Xpfx7>50=f:kmwqYwayogeck ioqw[djr'DkohR}zm^cg`5678Vrd~1<6>3g8mkusWyc{iagae.kmwqYfd|%FmijPsto\eab789:Ttb|32?0e?lht|Vzb|hbfnd-jjvrXie$Aljk_rwn[dbc89:;Sua}<22=6c=nfz~T|d~jlhlf+lht|Vkgy"Cnde]pqhYflm:;<=Qwos>05;4a3`dxxR~fpdnjj`)nfz~Tma{ M`fg[vsjWhno<=>?_ymq8649:l1bb~zPphrfhlhb'`dxxRocu.Ob`aYt}dUjhi>?01]{kw:46;o0ec}{_qksaioim&ceyQnlt-NeabX{|gTmij?012\|jt;<78n7d`|t^rjt`jnfl%bb~zPamw,IdbcWzfSljk0123[}iu4<49i6gasu]smuckago$ec}{_`nv+HgclVy~aRokd1234Z~hz5<5>h5fnrv\tlvbd`dn#d`|t^coq*KflmUxy`Qnde2345Yg{6<2?k4ioqw[uowmecei"gasu]bhp)JimnTxcPaef3456Xpfx743218mkusWyc{iagae.kmwqYfd|%Fobcas]fuZejxVoz<=>?_b{?5684;2ceyQiqgomkc(agySlbz/LaliuguWl{To`~Pep2345Ydq5;?2>=4ioqw[uowmecei"gasu]bhp)Jkfg{mQjq^antZcv89:;Snw314<06>oi{}U{e}kciog,mkusWhf~#@m`mqcq[`wXkdzTi|>?01]`}979;;1bb~zPphrfhlhb'`dxxRocu.O`khvfzVozSnc_ds3456Xkp692><4ioqw[uowmecei"gasu]bhp)Jkfg{mQjq^antZcv89:;Snw33?11?lht|Vzb|hbfnd-jjvrXie$Anabp`p\atYdeyUn}=>?0^az8184:2ceyQiqgomkc(agySlbz/LaliuguWl{To`~Pep2345Ydq5?5??5fnrv\tlvbd`dn#d`|t^coq*Kdgdzj~Rk~_bos[`w789:Tot29>208mkusWyc{iagae.kmwqYfd|%Fobcas]fuZejxVoz<=>?_b{?3;553`dxxR~fpdnjj`)nfz~Tma{ MbmntdtXmxUha}Qjq1234Ze~4148>6gasu]smuckago$ec}{_`nv+HeheykyShPclr\at6789Uhu171329jjvrXx`zn`d`j/hlppZgk}&Ghc`~nr^gr[fkwWl{;<=>Pltv?4;533`dxxR~fpdnjj`)nfz~Tma{ MbmntdtXmxUha}Qjq1234Zjr|5;;2>:4ioqw[uowmecei"gasu]bhp)Jkfg{mQjq^antZcv89:;Sa{{<03=71=nfz~T|d~jlhlf+lht|Vkgy"ClolrbvZcvWjg{Sh?012\hpr;9;4886gasu]smuckago$ec}{_`nv+HeheykyShPclr\at6789Ugyy2>3?17?lht|Vzb|hbfnd-jjvrXie$Anabp`p\atYdeyUn}=>?0^nvp9736:>0ec}{_qksaioim&ceyQnlt-Ngjkwi{Un}Rmbp^gr4567We0<;1329jjvrXx`zn`d`j/hlppZgk}&Ghc`~nr^gr[fkwWl{;<=>Pltv?5;543`dxxR~fpdnjj`)nfz~Tma{ MbmntdtXmxUha}Qjq1234Zjr|585?>5fnrv\tlvbd`dn#d`|t^coq*Kdgdzj~Rk~_bos[`w789:T`xz33?10?lht|Vzb|hbfnd-jjvrXie$Anabp`p\atYdeyUn}=>?0^nvp929;:1bb~zPphrfhlhb'`dxxRocu.O`khvfzVozSnc_ds3456Xd|~793=<;hlppZvnxlfbbh!fnrv\eis(Ejef|l|Pep]`iuYby9:;Pltv?=;4e3`dxxR~fpdnjj`)nfz~Tma{ Mlw{[wct}e~T>Rh9_RU36g=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V8Tj;Q\W004?lht|Vzb|hbfnd-jjvrXie$A`{w_sgpqirX;Vl>>95fnrv\tlvbd`dn#d`|t^coq*Kj}qUyi~{ct^613>oi{}U{e}kciog,mkusWhf~#@czx^pfwpjsW=Um9?:4ioqw[uowmecei"gasu]bhp)Je|rT~h}zlu]660=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V?:>:5fnrv\tlvbd`dn#d`|t^coq*Kj}qUyi~{ct^7\b04?3`dxxR~fpdnjj`)nfz~Tma{ Mlw{[wct}e~T9Rh:13;8mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY2Wo?:Sk;>33;8mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY2Wo?:8?74ioqw[uowmecei"gasu]bhp)Je|rT~h}zlu]6[c36=;30ec}{_qksaioim&ceyQnlt-Nip~Xzly~`yQ:_g7227?Sk;>73;8mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY2Wo?:4?74ioqw[uowmecei"gasu]bhp)Je|rT~h}zlu]6[c361;20ec}{_qksaioim&ceyQnlt-Nip~Xzly~`yQ:_g716<=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V?Tj845fnrv\tlvbd`dn#d`|t^coq*Kj}qUyi~{ct^7\b045:01bb~zPphrfhlhb'`dxxRocu.Onq}YumzgxR;Pf4006<=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V?Tj8<;289jjvrXx`zn`d`j/hlppZgk}&GfyuQ}erwopZ3Xn<8>>45fnrv\tlvbd`dn#d`|t^coq*Kj}qUyi~{ct^7\b041:01bb~zPphrfhlhb'`dxxRocu.Onq}YumzgxR;Pf4046<=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V?Tj8<7289jjvrXx`zn`d`j/hlppZgk}&GfyuQ}erwopZ3Xn<82>55fnrv\tlvbd`dn#d`|t^coq*Kj}qUyi~{ct^7\b05512ceyQiqgomkc(agySlbz/Lov|Ztb{|fS8Qi5221<>oi{}U{e}kciog,mkusWhf~#@czx^pfwpjsWSk;P03;8mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY2Wo?T=?o4ioqw[uowmecei"gasu]bhp)Je|rT~h}zlu]6[c3X998j7d`|t^rjt`jnfl%bb~zPamw,IhsW{oxyazP5^d6[475i2ceyQiqgomkc(agySlbz/Lov|Ztb{|fS8Qi5^316d=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V?Tj8Q>33c8mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY2Wo?T=9Sk;P190b?lht|Vzb|hbfnd-jjvrXie$A`{w_sgpqirX=Vl>S<7=9:kmwqYwayogeck ioqw[djr'Dg~tR|jstnw[0Ya=V89m6gasu]smuckago$ec}{_`nv+HkrpVxnxb{_4]e1Z47:h1bb~zPphrfhlhb'`dxxRocu.Onq}YumzgxR;Pf4]157gSk;P230b?lht|Vzb|hbfnd-jjvrXie$A`{w_sgpqirX=Vl>S?==a:kmwqYwayogeck ioqw[djr'Dg~tR|jstnw[0Ya=V8?>l5fnrv\tlvbd`dn#d`|t^coq*Kj}qUyi~{ct^7\b0Y5=;k0ec}{_qksaioim&ceyQnlt-Nip~Xzly~`yQ:_g7\634f3`dxxR~fpdnjj`)nfz~Tma{ Mlw{[wct}e~T9Rh:_351e>oi{}U{e}kciog,mkusWhf~#@czx^pfwpjsWSk;P53;8mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY2Wo?T:?74ioqw[uowmecei"gasu]bhp)Je|rT~h}zlu]6[c3X?;30ec}{_qksaioim&ceyQnlt-Nip~Xzly~`yQ:_g7\<7?Sk;P9368mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY1:<1bb~zPphrfhlhb'`dxxRocu.Onq}YumzgxR8>279jjvrXx`zn`d`j/hlppZgk}&GfyuQ}erwopZ068;<0ec}{_qksaioim&ceyQnlt-Nip~Xzly~`yQ91005?lht|Vzb|hbfnd-jjvrXie$A`{w_sgpqirX>889:6gasu]smuckago$ec}{_`nv+HkrpVxnxb{_73063=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V<:8?84ioqw[uowmecei"gasu]bhp)Je|rT~h}zlu]550413`dxxR~fpdnjj`)nfz~Tma{ Mlw{[wct}e~T:<8=6:kmwqYwayogeck ioqw[djr'Dg~tR|jstnw[370:?1bb~zPphrfhlhb'`dxxRocu.Onq}YumzgxR8>8348mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY1908>7d`|t^rjt`jnfl%bb~zPamw,IhsW{oxyazP6305?lht|Vzb|hbfnd-jjvrXie$A`{w_sgpqirX>;:9:6gasu]smuckago$ec}{_`nv+HkrpVxnxb{_70263=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V<9>?84ioqw[uowmecei"gasu]bhp)Je|rT~h}zlu]566413`dxxR~fpdnjj`)nfz~Tma{ Mlw{[wct}e~T:?:=6:kmwqYwayogeck ioqw[djr'Dg~tR|jstnw[342:?1bb~zPphrfhlhb'`dxxRocu.Onq}YumzgxR8=6348mkusWyc{iagae.kmwqYfd|%FaxvPrdqvhqY1:>8=7d`|t^rjt`jnfl%bb~zPamw,IhsW{oxyazP63:12>oi{}U{e}kciog,mkusWhf~#@czx^pfwpjsW?82>85fnrv\tlvbd`dn#d`|t^coq*Kj}qUyi~{ct^4063=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V<82ceyQiqgomkc(agySlbz/Lov|Ztb{|fS:?=279jjvrXx`zn`d`j/hlppZgk}&GfyuQ}erwopZ16;;<0ec}{_qksaioim&ceyQnlt-Nip~Xzly~`yQ81505?lht|Vzb|hbfnd-jjvrXie$A`{w_sgpqirX?8?9:6gasu]smuckago$ec}{_`nv+HkrpVxnxb{_63563=nfz~T|d~jlhlf+lht|Vkgy"Cbuy]qavsk|V=:;?84ioqw[uowmecei"gasu]bhp)Je|rT~h}zlu]45=413`dxxR~fpdnjj`)nfz~Tma{ Mlw{[wct}e~T;<7=5:kmwqYwayogeck ioqw[djr'Dg~tR|jstnw[245>2ceyQiqgomkc(agySlbz/Lov|Ztb{|fS:7d`|t^rjt`jnfl%bb~zPamw,IhsW{oxyazP7406?lht|Vzb|hbfnd-jjvrXie$A`{w_sgpqirX??8>7d`|t^rjt`jnfl%bb~zPamw,IhsW{oxyazP7606?lht|Vzb|hbfnd-jjvrXie$A`{w_sgpqirX?18>7d`|t^rjt`jnfl%bb~zPamw,IhsW{oxyazP7803?lht|Vzb|hbfnd-jjvrXie$jaohs^nww4goi{}U{e}kciog,mkusWhf~#~{b_sgp8459:;1bb~zPphrfhlhb'`dxxRocu.qviZtb{5;?2?<4ioqw[uowmecei"gasu]bhp)t}dUyi~2>5?01?lht|Vzb|hbfnd-jjvrXie$xcPrdq?5385:2ceyQiqgomkc(agySlbz/rwn[wct48=5>?5fnrv\tlvbd`dn#d`|t^coq*ureVxn1?7>308mkusWyc{iagae.kmwqYfd|%xy`Q}er>2=;463`dxxR~fpdnjj`)nfz~Tma{ sto\v`u;97897d`|t^rjt`jnfl%bb~zPamw,wpkXzly7>=0=2:kmwqYwayogeck ioqw[djr'zfSk|<33=67=nfz~T|d~jlhlf+lht|Vkgy"}zm^pfw9456;80ec}{_qksaioim&ceyQnlt-pqhYumz69?3<=;hlppZvnxlfbbh!fnrv\eis({|gT~h}325<16>oi{}U{e}kciog,mkusWhf~#~{b_sgp8739:;1bb~zPphrfhlhb'`dxxRocu.qviZtb{58=2?<4ioqw[uowmecei"gasu]bhp)t}dUyi~2=7?01?lht|Vzb|hbfnd-jjvrXie$xcPrdq?6=85:2ceyQiqgomkc(agySlbz/rwn[wct4;35><5fnrv\tlvbd`dn#d`|t^coq*ureVxn1<1239jjvrXx`zn`d`j/hlppZgk}&y~aR|js=13:74;hlppZvnxlfbbh!fnrv\eis({|gT~h}34?02?lht|Vzb|hbfnd-jjvrXie$xcPrdq?1;463`dxxR~fpdnjj`)nfz~Tma{ sto\v`u;>78:7d`|t^rjt`jnfl%bb~zPamw,wpkXzly7;3<>;hlppZvnxlfbbh!fnrv\eis({|gT~h}38?02?lht|Vzb|hbfnd-jjvrXie$xcPrdq?=;5?3`dxxR~fpdnjj`)nfz~Tnn{ MbmntdtXnekl#k~_bos[`w789:Tot2?>2;8mkusWyc{iagae.kmwqYek|%Fobcas]ehdat&l{To`~Pep2345Ydq5;;2>74ioqw[uowmecei"gasu]agp)Jkfg{mQil`ep*`wXkdzTi|>?01]`}9766:30ec}{_qksaioim&ceyQmct-Ngjkwi{Um`li|.ds\ghvXmx:;<=Qly=31:6?2;8mkusWyc{iagae.kmwqYek|%Fobcas]ehdat&l{To`~Pep2345Ydq5;?2>74ioqw[uowmecei"gasu]agp)Jkfg{mQil`ep*`wXkdzTi|>?01]`}9726:20ec}{_qksaioim&ceyQmct-Ngjkwi{Um`li|.ds\ghvXmx:;<=Qly=3=7==nfz~T|d~jlhlf+lht|Vhhy"ClolrbvZ`kiny%i|Qlmq]fu5678Vir0?0<8:kmwqYwayogeck ioqw[ger'Dida}o}_gnbcv(byVif|Rk~0123[f;;7937d`|t^rjt`jnfl%bb~zPbbw,IfijxhxTjaohs/gr[fkwWl{;<=>Pcx>7:6>?_b{?3;5?3`dxxR~fpdnjj`)nfz~Tnn{ MbmntdtXnekl#k~_bos[`w789:Tot27>2:8mkusWyc{iagae.kmwqYek|%Fobcas]ehdat&l{To`~Pep2345Ydq535?45fnrv\tlvbd`dn#d`|t^``q*Kdgdzj~Rhcafq-atYdeyUn}=>?0^nvp969;h1bb~zPphrfhlhb'`dxxRllu.O`khvfzVlgmj}!ep]`iuYby9:;1?1b?lht|Vzb|hbfnd-jjvrXjj$Anabp`p\big`{'ozSnc_ds3456Xd|~7=?0?0^nvp9736:k0ec}{_qksaioim&ceyQmct-Ngjkwi{Um`li|.ds\ghvXmx:;<=Qcuu>21;5>3`dxxR~fpdnjj`)nfz~Tnn{ MbmntdtXnekl#k~_bos[`w789:T`xz31?1:?lht|Vzb|hbfnd-jjvrXjj$Anabp`p\big`{'ozSnc_ds3456Xd|~7>3=6;hlppZvnxlfbbh!fnrv\ffs(Ejef|l|Pfmcdw+cvWjg{Sh?012\hpr;;7927d`|t^rjt`jnfl%bb~zPbbw,IfijxhxTjaohs/gr[fkwWl{;<=>Pltv?0;5>3`dxxR~fpdnjj`)nfz~Tnn{ MbmntdtXnekl#k~_bos[`w789:T`xz35?1:?lht|Vzb|hbfnd-jjvrXjj$Anabp`p\big`{'ozSnc_ds3456Xd|~7:3=6;hlppZvnxlfbbh!fnrv\ffs(Ejef|l|Pfmcdw+cvWjg{Sh?012\hpr;?7927d`|t^rjt`jnfl%bb~zPbbw,IfijxhxTjaohs/gr[fkwWl{;<=>Pltv?<;5>3`dxxR~fpdnjj`)nfz~Tnn{ MbmntdtXnekl#k~_bos[`w789:T`xz39?01?lht|Vzb|hbfnd-jjvrXkfz$NljYAefq8585;2ceyQiqgomkc(agySna/CcgRDbcz5;;2?=4ioqw[uowmecei"gasu]`ku)Eim\Jhi|310<17>oi{}U{e}kciog,mkusWje{#OokV@fgv9756;90ec}{_qksaioim&ceyQloq-AeaPFlmx7=>0=3:kmwqYwayogeck ioqw[fiw'KkoZLjkr=37:75318mkusWyc{iagae.kmwqYdgy%ImiXNdep?5285;2ceyQiqgomkc(agySna/CcgRDbcz5;32?=4ioqw[uowmecei"gasu]`ku)Eim\Jhi|318<16>oi{}U{e}kciog,mkusWje{#OokV@fgv979::1bb~zPphrfhlhb'`dxxRm`p.@b`SGcl{69<3<<;hlppZvnxlfbbh!fnrv\gjv(Jhn]Mij}<33=66=nfz~T|d~jlhlf+lht|Vid|"LndWCg`w:5:7887d`|t^rjt`jnfl%bb~zPcnr,FdbQImny0?=1229jjvrXx`zn`d`j/hlppZehx&Hjh[Okds>10;443`dxxR~fpdnjj`)nfz~Tob~ B`fUEabu4;?5>>5fnrv\tlvbd`dn#d`|t^alt*Dfl_Koh2=6?00?lht|Vzb|hbfnd-jjvrXkfz$NljYAefq8719::1bb~zPphrfhlhb'`dxxRm`p.@b`SGcl{6943<<;hlppZvnxlfbbh!fnrv\gjv(Jhn]Mij}<3;=67=nfz~T|d~jlhlf+lht|Vid|"LndWCg`w:56;90ec}{_qksaioim&ceyQloq-AeaPFlmx7?=0=3:kmwqYwayogeck ioqw[fiw'KkoZLjkr=12:74oi{}U{e}kciog,mkusWje{#OokV@fgv9?9:81bb~zPphrfhlhb'`dxxRm`p.@b`SGcl{U;><5fnrv\tlvbd`dn#d`|t^alt*Dfl_KohQ>239jjvrXx`zn`d`j/hlppZehx&Hjh[Okds]2474oi{}U{e}kciog,mkusWje{#OokV@fgvZ70:;1bb~zPphrfhlhb'`dxxRm`p.@b`SGcl{U:4?<4ioqw[uowmecei"gasu]`ku)Eim\Jhi|P1802?lht|Vzb|hbfnd-jjvrXkfz$NljYAefq[7453`dxxR~fpdnjj`)nfz~Tob~ B`fUEabuW;:9>6gasu]smuckago$ec}{_bms+Ggc^Hno~R<>239jjvrXx`zn`d`j/hlppZehx&Hjh[Okds]1674;80ec}{_qksaioim&ceyQloq-AeaPFlmxT>:<=;hlppZvnxlfbbh!fnrv\gjv(Jhn]Mij}_3:16>oi{}U{e}kciog,mkusWje{#OokV@fgvZ4>:81bb~zPphrfhlhb'`dxxRm`p.@b`SGcl{U8>?5fnrv\tlvbd`dn#d`|t^alt*Dfl_KohQ<0308mkusWyc{iagae.kmwqYdgy%ImiXNdep\74463`dxxR~fpdnjj`)nfz~Tob~ B`fUEabuW=8:7d`|t^rjt`jnfl%bb~zPcnr,FdbQImnyS8<>;hlppZvnxlfbbh!fnrv\gjv(Jhn]Mij}_702?lht|Vzb|hbfnd-jjvrXkfz$NljYAefq[2463`dxxR~fpdnjj`)nfz~Tob~ B`fUEabuW18:7d`|t^rjt`jnfl%bb~zPcnr,FdbQImnyS4?0=31:7d312<1f>oi{}U{e}kciog,mkusWje{#OokV@fgvZkrp9:;<1?;>3`8mkusWyc{iagae.kmwqYdgy%ImiXNdep\ip~789:7=80=b:kmwqYwayogeck ioqw[fiw'KkoZLjkr^ov|56785;=2?l4ioqw[uowmecei"gasu]`ku)Eim\Jhi|Pmtz3456;9>49n6gasu]smuckago$ec}{_bms+Ggc^Hno~Rczx123497?6;h0ec}{_qksaioim&ceyQloq-AeaPFlmxTaxv?012?5<85i2ceyQiqgomkc(agySna/CcgRDbczVg~t=>?0=3=6g=nfz~T|d~jlhlf+lht|Vid|"LndWCg`wYj}q:;<=2=0?0a?lht|Vzb|hbfnd-jjvrXkfz$NljYAefq[hs89:;0??12c9jjvrXx`zn`d`j/hlppZehx&Hjh[Okds]nq}678969>3o5fnrv\tlvbd`dn#d`|t^alt*Dfl_KohQbuy2345:5<78i7d`|t^rjt`jnfl%bb~zPcnr,FdbQImnyS`{w01238739:k1bb~zPphrfhlhb'`dxxRm`p.@b`SGcl{Ufyu>?01>12;4e3`dxxR~fpdnjj`)nfz~Tob~ B`fUEabuWds<=>?<35=6g=nfz~T|d~jlhlf+lht|Vid|"LndWCg`wYj}q:;<=2=8?0a?lht|Vzb|hbfnd-jjvrXkfz$NljYAefq[hs89:;0?712`9jjvrXx`zn`d`j/hlppZehx&Hjh[Okds]nq}6789692?l4ioqw[uowmecei"gasu]`ku)Eim\Jhi|Pmtz3456;;949n6gasu]smuckago$ec}{_bms+Ggc^Hno~Rczx12349566;k0ec}{_qksaioim&ceyQloq-AeaPFlmxTaxv?012?7;4f3`dxxR~fpdnjj`)nfz~Tob~ B`fUEabuWds<=>?<5<1e>oi{}U{e}kciog,mkusWje{#OokV@fgvZkrp9:;<1;12`9jjvrXx`zn`d`j/hlppZehx&Hjh[Okds]nq}67896=2?o4ioqw[uowmecei"gasu]`ku)Eim\Jhi|Pmtz3456;?78j7d`|t^rjt`jnfl%bb~zPcnr,FdbQImnyS`{w01238=85i2ceyQiqgomkc(agySna/CcgRDbczVg~t=>?0=;=62=nfz~T|d~jlhlf+lht|Vid|"LndWCg`wYig}:;<<<7;hlppZvnxlfbbh!fnrv\gjv(Jhn]Mij}_omw45669;20ec}{_qksaioim&ceyQloq-AeaPFlmxTbbz?01316f=nfz~T|d~jlhlf+lht|Vid|"LndWCg`wYig}:;<<oi{}U{e}kciog,mkusWje{#@czx^@b`SGcl{Ufyu>?013357c?=f:kmwqYwayogeck ioqw[fiw'Dg~tRLndWCg`wYj}q:;<=?;13d8mkusWyc{iagae.kmwqYdgy%FaxvPB`fUEabuWds<=>?1431b>oi{}U{e}kciog,mkusWje{#@czx^@b`SGcl{Ufyu>?013557`<2g9jjvrXx`zn`d`j/hlppZehx&GfyuQMaeTB`atXe|r;<=>=200e?lht|Vzb|hbfnd-jjvrXkfz$A`{w_CcgRDbczVg~t=>?03126c=nfz~T|d~jlhlf+lht|Vid|"Cbuy]AeaPFlmxTaxv?0121044a3`dxxR~fpdnjj`)nfz~Tob~ Mlw{[Ggc^Hno~Rczx1234736:o1bb~zPphrfhlhb'`dxxRm`p.Onq}YEim\Jhi|Pmtz34565>88m7d`|t^rjt`jnfl%bb~zPcnr,IhsWKkoZLjkr^ov|5678;=:>k5fnrv\tlvbd`dn#d`|t^alt*Kj}qUImiXNdep\ip~789:94<2g9jjvrXx`zn`d`j/hlppZehx&GfyuQMaeTB`atXe|r;<=><000f?lht|Vzb|hbfnd-jjvrXkfz$A`{w_CcgRDbczVg~t=>?0231b>oi{}U{e}kciog,mkusWje{#@czx^@b`SGcl{Ufyu>?011257`88n7d`|t^rjt`jnfl%bb~zPcnr,IhsWKkoZLjkr^ov|5678>;9i6gasu]smuckago$ec}{_bms+HkrpVHjh[Okds]nq}67892:>h5fnrv\tlvbd`dn#d`|t^alt*Kj}qUImiXNdep\ip~789:2=<74ioqw[uowmecei"gasu]`ku)I8830ec}{_qksaioim&ceyQloq-M34?oi{}U{e}kciog,mkusWje{#na_qksaZC_&mceS<==9:kmwqYwayogeck ioqw[fiw'je{S}ge^G[*aoiW8>956gasu]smuckago$ec}{_bms+fiwWyc{iRKW.ekm[43512ceyQiqgomkc(agySna/bms[uowmVOS"iga_041=>oi{}U{e}kciog,mkusWje{#na_qksaZC_&mceS<9=9:kmwqYwayogeck ioqw[fiw'je{S}ge^G[*aoiW82956gasu]smuckago$ec}{_bms+fiwWyc{iRKW.ekm[4?502ceyQiqgomkc(agySna/bms[uowmVOS"iga_30:?lht|Vzb|hbfnd-jjvrXkfz$ob~Pphrf[@^)l`dT>=<6;hlppZvnxlfbbh!fnrv\gjv(kfzT|d~j_DZ-`lhX:8827d`|t^rjt`jnfl%bb~zPcnr,gjvXx`znSHV!dhl\674>3`dxxR~fpdnjj`)nfz~Tob~ cnr\tlvbWLR%hd`P220:?lht|Vzb|hbfnd-jjvrXkfz$ob~Pphrf[@^)l`dT>9<6;hlppZvnxlfbbh!fnrv\gjv(kfzT|d~j_DZ-`lhX:<827d`|t^rjt`jnfl%bb~zPcnr,gjvXx`znSHV!dhl\634>3`dxxR~fpdnjj`)nfz~Tob~ cnr\tlvbWLR%hd`P260:?lht|Vzb|hbfnd-jjvrXkfz$ob~Pphrf[@^)l`dT>5<6;hlppZvnxlfbbh!fnrv\gjv(kfzT|d~j_DZ-`lhX:0837d`|t^rjt`jnfl%bb~zPcnr,gjvXx`znSHV!dhl\77?oi{}U{e}kciog,mkusWje{#na_qksaZC_&mceS;<7;hlppZvnxlfbbh!fnrv\gjv(kfzT|d~j_DZ-`lhX?;20ec}{_qksaioim&ceyQloq-`kuYwayoTIU kio];6==nfz~T|d~jlhlf+lht|Vid|"m`p^rjt`YBP'nbbR7=7:kmwqYwayogeck ioqw[fiw'je{S}ge^G[*wbX8;=0ec}{_qksaioim&ceyQloq-`kuYwayoTIU }d^313>oi{}U{e}kciog,mkusWje{#na_qksaZC_&{nT>?94ioqw[uowmecei"gasu]`ku)dgyU{e}kPEY,q`Z55?2ceyQiqgomkc(agySna/bms[uowmVOS"jP4378mkusWyc{iagae.kmwqYdgy%hc}Qiqg\A](um;?0ec}{_qksaioim&ceyQloq-`kuYwayoTIU xe228mkusWyc{iagae.kmwqYdgy%hc}Qiqg\A]YulVey<=>?_hlu74=nfz~T|d~jlhlf+lht|Vid|"m`p^rjt`YBPVxoSb|?012\mkp6:<1bb~zPphrfhlhb'`dxxRm`p.altZvnxlUBHR|j2e9jjvrXx`zn`d`j/hlppZehx&id|R~fpd]J@ZtbWZ];S^Y?249jjvrXx`zn`d`j/hlppZehx&id|R~fpd]J@Zqb:01bb~zPphrfhlhb'`dxxRm`p.altZvnxlUBHRyj_RU36==nfz~T|d~jlhlf+lht|Vid|"m{rm]lqq(bpjUntdz=a:kmwqYwayogeck ioqw[fiw'j~y`Razt/g{gZpbkV89>?5fnrv\tlvbd`dn#d`|t^alt*eszeUdyyQjc318mkusWyc{iagae.kmwqYdgy%hxbPotv\af75:2ceyQiqgomkc(agySna/bvqhZir|Von?>5fnrv\tlvbd`dn#d`|t^alt*eszeUdyyQjxb]f|lrXkdzTi|>?0114?lht|Vzb|hbfnd-jjvrXkfz$oy|c_nww[`~dWlrbxRmbp^gr4567WZ];?=5fnrv\tlvbd`dn#d`|t^alt*eszeUdyyQjxb]f|lrXe|r;<=><1:kmwqYwayogeck ioqw[fiw'j~y`Razt^g{gZca}Ufyu>?01304>oi{}U{e}kciog,mkusWje{#nz}l^mvpZckVoseyQaou2344563`dxxR~fpdnjj`)nfz~Tob~ cupo[jssWlrhShvft^llp56798;n7d`|t^rjt`jnfl%bb~zPcnr,`jss494:j6gasu]smuckago$ec}{_bms+air|5;;2f:kmwqYwayogeck ioqw[fiw'me~x1?=>0d8mkusWyc{iagae.kmwqYdgy%ocxz312<2b>oi{}U{e}kciog,mkusWje{#iazt=37:4`4:j6gasu]smuckago$ec}{_bms+air|5;32e:kmwqYwayogeck ioqw[fiw'me~x1?11g9jjvrXx`zn`d`j/hlppZehx&ndyy2=0?3e?lht|Vzb|hbfnd-jjvrXkfz$hb{{<33=5c=nfz~T|d~jlhlf+lht|Vid|"j`uu>16;7a3`dxxR~fpdnjj`)nfz~Tob~ dnww87599o1bb~zPphrfhlhb'`dxxRm`p.flqq:5<7;m7d`|t^rjt`jnfl%bb~zPcnr,`jss4;?5=k5fnrv\tlvbd`dn#d`|t^alt*bh}}69:3?i;hlppZvnxlfbbh!fnrv\gjv(lf0?911g9jjvrXx`zn`d`j/hlppZehx&ndyy2=8?3e?lht|Vzb|hbfnd-jjvrXkfz$hb{{<3;=5`=nfz~T|d~jlhlf+lht|Vid|"j`uu>1:4`e:kmwqYwayogeck ioqw[fiw'me~x1711e9jjvrXx`zn`d`j/hlppZehx&ndyyQ?1e9jjvrXx`zn`d`j/hlppZehx&ndyyQ>1d9jjvrXx`zn`d`j/hlppZehx&ndyyQ>00g8mkusWyc{iagae.kmwqYdgy%ocxzP103f?lht|Vzb|hbfnd-jjvrXkfz$hb{{_002a>oi{}U{e}kciog,mkusWje{#iazt^305`=nfz~T|d~jlhlf+lht|Vid|"j`uu]204c>?j;hlppZvnxlfbbh!fnrv\gjv(lfS?:>e:kmwqYwayogeck ioqw[fiw'me~xR<:1d9jjvrXx`zn`d`j/hlppZehx&ndyyQ=60g8mkusWyc{iagae.kmwqYdgy%ocxzP263f?lht|Vzb|hbfnd-jjvrXkfz$hb{{_3:2a>oi{}U{e}kciog,mkusWje{#iazt^0:5a=nfz~T|d~jlhlf+lht|Vid|"j`uu]05`=nfz~T|d~jlhlf+lht|Vid|"j`uu]044c95fnrv\tlvbd`dn#d`|t^alt*bh}}Ujbi>?01312>oi{}U{e}kciog,mkusWje{#iazt^antZcv89:;>:5fnrv\tlvbd`dn#d`|t^alt*bh}}Uha}Qjq12344413`dxxR~fpdnjj`)nfz~Tob~ dnww[fkwWl{;<=?=7:kmwqYwayogeck ioqw[fiw'me~xRmbp^gr45669;<0ec}{_qksaioim&ceyQloq-gkprXkdzTi|>?0304?lht|Vzb|hbfnd-jjvrXkfz$hb{{_bos[`w7898:>;5fnrv\tlvbd`dn#d`|t^alt*bh}}Uha}Qjq123771?=6:kmwqYwayogeck ioqw[fiw'me~xRmbp^gr4562:>1bb~zPphrfhlhb'`dxxRm`p.flqqYdeyUn}=>?5005?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{45674949o6gasu]smuckago$ec}{_bms+air|Vg~t=>?0=2=50YT_9837d`|t^rjt`jnfl%bb~zPcnr,`jssWds<=>?<1<027>?0=33:7?53;8mkusWyc{iagae.kmwqYdgy%ocxzPmtz3456;994:;?64ioqw[uowmecei"gasu]`ku)cg|~Taxv?012?5583:>1bb~zPphrfhlhb'`dxxRm`p.flqqYj}q:;<=2>1?0:?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{456748;5=8<6;hlppZvnxlfbbh!fnrv\gjv(lfS`{w012384799>837d`|t^rjt`jnfl%bb~zPcnr,`jssWds<=>?<03=071?0=31:41502ceyQiqgomkc(agySna/emvpZkrp9:;<1?=>504?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{45674895>45fnrv\tlvbd`dn#d`|t^alt*bh}}Ufyu>?01>27;72:01bb~zPphrfhlhb'`dxxRm`p.flqqYj}q:;<=2>3?346==nfz~T|d~jlhlf+lht|Vid|"j`uu]nq}67896:?3:=7:kmwqYwayogeck ioqw[fiw'me~xRczx12349736;30ec}{_qksaioim&ceyQloq-gkprXe|r;<=>315<217?73:8mkusWyc{iagae.kmwqYdgy%ocxzPmtz3456;9=4?>:5fnrv\tlvbd`dn#d`|t^alt*bh}}Ufyu>?01>21;4>3`dxxR~fpdnjj`)nfz~Tob~ dnww[hs89:;0<;1140:?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{456748?5=:<7;hlppZvnxlfbbh!fnrv\gjv(lfS`{w01238439<;=0ec}{_qksaioim&ceyQloq-gkprXe|r;<=>317<1=>oi{}U{e}kciog,mkusWje{#iazt^ov|56785;=2<>=8:kmwqYwayogeck ioqw[fiw'me~xRczx12349716=837d`|t^rjt`jnfl%bb~zPcnr,`jssWds<=>?<04==71?0=34:14?3`dxxR~fpdnjj`)nfz~Tob~ dnww[hs89:;0<919358mkusWyc{iagae.kmwqYdgy%ocxzPmtz3456;914956gasu]smuckago$ec}{_bms+air|Vg~t=>?0=3;:46502ceyQiqgomkc(agySna/emvpZkrp9:;<1?7>50;?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{456748255?94ioqw[uowmecei"gasu]`ku)cg|~Taxv?012?5<8512ceyQiqgomkc(agySna/emvpZkrp9:;<1?6>021<>oi{}U{e}kciog,mkusWje{#iazt^ov|56785;229<7;hlppZvnxlfbbh!fnrv\gjv(lfS`{w012384?91;<0ec}{_qksaioim&ceyQloq-gkprXe|r;<=>31?0;?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{4567484:?0=03:46502ceyQiqgomkc(agySna/emvpZkrp9:;<150;?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{45674;:55?94ioqw[uowmecei"gasu]`ku)cg|~Taxv?012?648512ceyQiqgomkc(agySna/emvpZkrp9:;<1<>>021<>oi{}U{e}kciog,mkusWje{#iazt^ov|567858:29<7;hlppZvnxlfbbh!fnrv\gjv(lfS`{w012387791;=0ec}{_qksaioim&ceyQloq-gkprXe|r;<=>323<1=>oi{}U{e}kciog,mkusWje{#iazt^ov|56785892<>=8:kmwqYwayogeck ioqw[fiw'me~xRczx12349456=837d`|t^rjt`jnfl%bb~zPcnr,`jssWds<=>?<30==71>0=9:kmwqYwayogeck ioqw[fiw'me~xRczx123494468:946gasu]smuckago$ec}{_bms+air|Vg~t=>?0=00:14?3`dxxR~fpdnjj`)nfz~Tob~ dnww[hs89:;0?=19358mkusWyc{iagae.kmwqYdgy%ocxzPmtz3456;:=4956gasu]smuckago$ec}{_bms+air|Vg~t=>?0=07:46502ceyQiqgomkc(agySna/emvpZkrp9:;<1<;>50;?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{45674;>55?94ioqw[uowmecei"gasu]`ku)cg|~Taxv?012?608512ceyQiqgomkc(agySna/emvpZkrp9:;<1<:>021<>oi{}U{e}kciog,mkusWje{#iazt^ov|567858>29<7;hlppZvnxlfbbh!fnrv\gjv(lfS`{w012387391;=0ec}{_qksaioim&ceyQloq-gkprXe|r;<=>327<1=>oi{}U{e}kciog,mkusWje{#iazt^ov|567858=2<>=8:kmwqYwayogeck ioqw[fiw'me~xRczx12349416=837d`|t^rjt`jnfl%bb~zPcnr,`jssWds<=>?<34==71:0=9:kmwqYwayogeck ioqw[fiw'me~xRczx123494068:946gasu]smuckago$ec}{_bms+air|Vg~t=>?0=04:14?3`dxxR~fpdnjj`)nfz~Tob~ dnww[hs89:;0?919358mkusWyc{iagae.kmwqYdgy%ocxzPmtz3456;:14956gasu]smuckago$ec}{_bms+air|Vg~t=>?0=0;:46502ceyQiqgomkc(agySna/emvpZkrp9:;<1<7>50;?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{45674;255?94ioqw[uowmecei"gasu]`ku)cg|~Taxv?012?6<8512ceyQiqgomkc(agySna/emvpZkrp9:;<1<6>021<>oi{}U{e}kciog,mkusWje{#iazt^ov|567858229<7;hlppZvnxlfbbh!fnrv\gjv(lfS`{w012387?91;<0ec}{_qksaioim&ceyQloq-gkprXe|r;<=>32?0;?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{45674;4:9?64ioqw[uowmecei"gasu]`ku)cg|~Taxv?012?6;70:>1bb~zPphrfhlhb'`dxxRm`p.flqqYj}q:;<=2=>504?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{45674::5>45fnrv\tlvbd`dn#d`|t^alt*bh}}Ufyu>?01>04;77:11bb~zPphrfhlhb'`dxxRm`p.flqqYj}q:;<=2<0?61<>oi{}U{e}kciog,mkusWje{#iazt^ov|567859;24<8;hlppZvnxlfbbh!fnrv\gjv(lfS`{w01238679:01bb~zPphrfhlhb'`dxxRm`p.flqqYj}q:;<=2<1?366<=nfz~T|d~jlhlf+lht|Vid|"j`uu]nq}678968=3?8299jjvrXx`zn`d`j/hlppZehx&ndyyQbuy2345:497>9:6gasu]smuckago$ec}{_bms+air|Vg~t=>?0=1=6==nfz~T|d~jlhlf+lht|Vid|"j`uu]nq}6789682<;=8:kmwqYwayogeck ioqw[fiw'me~xRczx12349599>8<7d`|t^rjt`jnfl%bb~zPcnr,`jssWds<=>?<2<763=nfz~T|d~jlhlf+lht|Vid|"j`uu]nq}67896?2?64ioqw[uowmecei"gasu]`ku)cg|~Taxv?012?0;72:11bb~zPphrfhlhb'`dxxRm`p.flqqYj}q:;<=2;>0513>oi{}U{e}kciog,mkusWje{#iazt^ov|56785>58?84ioqw[uowmecei"gasu]`ku)cg|~Taxv?012?1;4?3`dxxR~fpdnjj`)nfz~Tob~ dnww[hs89:;080>53:8mkusWyc{iagae.kmwqYdgy%ocxzPmtz3456;=7;<>:5fnrv\tlvbd`dn#d`|t^alt*bh}}Ufyu>?01>6:1413`dxxR~fpdnjj`)nfz~Tob~ dnww[hs89:;0;0=8:kmwqYwayogeck ioqw[fiw'me~xRczx1234909998<7d`|t^rjt`jnfl%bb~zPcnr,`jssWds<=>?<7<762=nfz~T|d~jlhlf+lht|Vid|"j`uu]nq}67896=24<9;hlppZvnxlfbbh!fnrv\gjv(lfS`{w0123828502ceyQiqgomkc(agySna/emvpZkrp9:;<1911104?lht|Vzb|hbfnd-jjvrXkfz$hb{{_lw{45674>4?>:5fnrv\tlvbd`dn#d`|t^alt*bh}}Ufyu>?01>4:<413`dxxR~fpdnjj`)nfz~Tob~ dnww[hs89:;050=8:kmwqYwayogeck ioqw[fiw'me~xRczx12349>99<837d`|t^rjt`jnfl%bb~zPcnr,`jssWds<=>?<9<23713;1<>oi{}U{e}kciog,mkusWje{#iazt^ov|56785359?<7;hlppZvnxlfbbh!fnrv\gjv(lfS`{w01238<81;;=0ec}{_qksaioim&ceyQloq-gkprXe|r;<=>39?:17>oi{}U{e}kciog,mkusWje{#hhcafq\Mkr60;80ec}{_qksaioim&ceyQloq-fbig`{VCex9<=;hlppZvnxlfbbh!fnrv\gjv(mofjk~QFnu;14>oi{}U{e}kciog,mkusWje{#hhcafq\Ks463`dxxR~fpdnjj`)nfz~Tob~ egnbcvYH~8;o7d`|t^rjt`jnfl%bb~zPcnr,aue;87;n7d`|t^rjt`jnfl%bb~zPcnr,aue;994:i6gasu]smuckago$ec}{_bms+`vd48;5=h5fnrv\tlvbd`dn#d`|t^alt*cwk5;92e:kmwqYwayogeck ioqw[fiw'lzh0<;11d9jjvrXx`zn`d`j/hlppZehx&o{o1?9>0g8mkusWyc{iagae.kmwqYdgy%n|n2>7?3f?lht|Vzb|hbfnd-jjvrXkfz$i}m319<2a>oi{}U{e}kciog,mkusWje{#h~l<0;=5a=nfz~T|d~jlhlf+lht|Vid|"kc=3=5`=nfz~T|d~jlhlf+lht|Vid|"kc=03:4c15;7b3`dxxR~fpdnjj`)nfz~Tob~ eqa?6786m2ceyQiqgomkc(agySna/dr`87599l1bb~zPphrfhlhb'`dxxRm`p.gsg94368o0ec}{_qksaioim&ceyQloq-ftf:5=7;n7d`|t^rjt`jnfl%bb~zPcnr,aue;:?4:i6gasu]smuckago$ec}{_bms+`vd4;=5=h5fnrv\tlvbd`dn#d`|t^alt*cwk58323?j;hlppZvnxlfbbh!fnrv\gjv(myi7?=0>e:kmwqYwayogeck ioqw[fiw'lzh0>?11e9jjvrXx`zn`d`j/hlppZehx&o{o1=11e9jjvrXx`zn`d`j/hlppZehx&o{o1:11e9jjvrXx`zn`d`j/hlppZehx&o{o1;11e9jjvrXx`zn`d`j/hlppZehx&o{o1811e9jjvrXx`zn`d`j/hlppZehx&o{o1911e9jjvrXx`zn`d`j/hlppZehx&o{o1611e9jjvrXx`zn`d`j/hlppZehx&o{o1711b9jjvrXx`zn`d`j/hlppZehx&o{oR>>c:kmwqYwayogeck ioqw[fiw'lzhS?k;hlppZvnxlfbbh!fnrv\gjv(myiT=9?k;hlppZvnxlfbbh!fnrv\gjv(myiT=8?k;hlppZvnxlfbbh!fnrv\gjv(myiT=;?k;hlppZvnxlfbbh!fnrv\gjv(myiT=:?k;hlppZvnxlfbbh!fnrv\gjv(myiT=5?k;hlppZvnxlfbbh!fnrv\gjv(myiT=4?l;hlppZvnxlfbbh!fnrv\gjv(myiT>:o6gasu]smuckago$ec}{_bms+`vdW<;h7d`|t^rjt`jnfl%bb~zPcnr,aueX>8i0ec}{_qksaioim&ceyQloq-ftfY09j1bb~zPphrfhlhb'`dxxRm`p.gsgZ>6k2ceyQiqgomkc(agySna/dr`[<423`dxxR~fpdnjj`)nfz~Tob~ eqa\ip~789;7<3<9;hlppZvnxlfbbh!fnrv\gjv(myiTaxv?013?4;75>2ceyQiqgomkc(agySna/dr`[hs89::0<>1269jjvrXx`zn`d`j/hlppZehx&o{oRczx1235977688=7d`|t^rjt`jnfl%bb~zPcnr,aueXe|r;<=?310<13>oi{}U{e}kciog,mkusWje{#h~l_lw{456648;5=?84ioqw[uowmecei"gasu]`ku)bxjUfyu>?00>26;403`dxxR~fpdnjj`)nfz~Tob~ eqa\ip~789;7=?0>279jjvrXx`zn`d`j/hlppZehx&o{oRczx12359746;=0ec}{_qksaioim&ceyQloq-ftfYj}q:;<<2>3?312>oi{}U{e}kciog,mkusWje{#h~l_lw{456648>5>:5fnrv\tlvbd`dn#d`|t^alt*cwkVg~t=>?1=37:4413`dxxR~fpdnjj`)nfz~Tob~ eqa\ip~789;7=80=7:kmwqYwayogeck ioqw[fiw'lzhS`{w012284399;<0ec}{_qksaioim&ceyQloq-ftfYj}q:;<<2>6?04?lht|Vzb|hbfnd-jjvrXkfz$i}mPmtz3457;9?4:>;5fnrv\tlvbd`dn#d`|t^alt*cwkVg~t=>?1=34:719:>1bb~zPphrfhlhb'`dxxRm`p.gsgZkrp9:;=1?7>005?lht|Vzb|hbfnd-jjvrXkfz$i}mPmtz3457;9049;6gasu]smuckago$ec}{_bms+`vdWds<=>><0;=573?00>2:4413`dxxR~fpdnjj`)nfz~Tob~ eqa\ip~789;7>=0=7:kmwqYwayogeck ioqw[fiw'lzhS`{w012287699;<0ec}{_qksaioim&ceyQloq-ftfYj}q:;<<2=1?04?lht|Vzb|hbfnd-jjvrXkfz$i}mPmtz3457;:84:>;5fnrv\tlvbd`dn#d`|t^alt*cwkVg~t=>?1=01:713?=6:kmwqYwayogeck ioqw[fiw'lzhS`{w01228759:>1bb~zPphrfhlhb'`dxxRm`p.gsgZkrp9:;=1<<>005?lht|Vzb|hbfnd-jjvrXkfz$i}mPmtz3457;:=49;6gasu]smuckago$ec}{_bms+`vdWds<=>><36=570358mkusWyc{iagae.kmwqYdgy%n|nQbuy2344:5>7;9:6gasu]smuckago$ec}{_bms+`vdWds<=>><35=62=nfz~T|d~jlhlf+lht|Vid|"kc^ov|567958<2<<9;hlppZvnxlfbbh!fnrv\gjv(myiTaxv?013?6=85?2ceyQiqgomkc(agySna/dr`[hs89::0?611348mkusWyc{iagae.kmwqYdgy%n|nQbuy2344:5178<7d`|t^rjt`jnfl%bb~zPcnr,aueXe|r;<=?328<260=nfz~T|d~jlhlf+lht|Vid|"kc^ov|5679585>;5fnrv\tlvbd`dn#d`|t^alt*cwkVg~t=>?1=0=570>358mkusWyc{iagae.kmwqYdgy%n|nQbuy2344:497;996gasu]smuckago$ec}{_bms+`vdWds<=>><2<12>oi{}U{e}kciog,mkusWje{#h~l_lw{45664:4:>85fnrv\tlvbd`dn#d`|t^alt*cwkVg~t=>?1=6=63=nfz~T|d~jlhlf+lht|Vid|"kc^ov|56795>5=?;4ioqw[uowmecei"gasu]`ku)bxjUfyu>?00>6:702<<:;hlppZvnxlfbbh!fnrv\gjv(myiTaxv?013?2;413`dxxR~fpdnjj`)nfz~Tob~ eqa\ip~789;7:3?=5:kmwqYwayogeck ioqw[fiw'lzhS`{w01228285>2ceyQiqgomkc(agySna/dr`[hs89::0:0>249jjvrXx`zn`d`j/hlppZehx&o{oRczx12359>9:?1bb~zPphrfhlhb'`dxxRm`p.gsgZkrp9:;=1611378mkusWyc{iagae.kmwqYdgy%n|nQbuy2344:>6;<0ec}{_qksaioim&ceyQloq-ftfYj}q:;<<26>002?lht|Vzb|hbfnd-jjvrXkfz$i}mPrde\s`453`dxxR~fpdnjj`)nfz~Tob~ eqa\v`aXl;9>6gasu]smuckago$ec}{_bms+`~dWjeoi1>1239jjvrXx`zn`d`j/hlppZehx&osoRm`dd>2:740=1:kmwqYwayogeck ioqw[fiw'lrhSnake^215>oi{}U{e}kciog,mkusWje{#hvl_bmgaZ7592ceyQiqgomkc(agySna/dz`[ficmV89=6gasu]smuckago$ec}{_bms+`~dWjeoiR==a:kmwqYwayogeck ioqw[fiw'lrhSnake^ov|56785;5>o5fnrv\tlvbd`dn#d`|t^alt*ckVidhhQbuy2345:6688j7d`|t^rjt`jnfl%bb~zPcnr,a}eXkfnnS`{w01238785j2ceyQiqgomkc(agySna/dz`[ficmVg~t=>?0=0=57g33?0a?lht|Vzb|hbfnd-jjvrXkfz$iumPcnff[hs89:;0>0>2`9jjvrXx`zn`d`j/hlppZehx&osoRm`dd]nq}67896?2?k4ioqw[uowmecei"gasu]`ku)bpjUhcikPmtz3456;<7UX[=<6;hlppZvnxlfbbh!fnrv\gjv(mqiTyo{e^DPIZ@Al88h7d`|t^rjt`jnfl%bb~zPcnr,a}eX{}kiRH\M^DE`4+Nf;n0ec}{_qksaioim&ceyQloq-f|fYt|h~nSK]B_GDg5(Oi9;30ec}{_qksaioim&ceyQloq-f|fYt|h~nSK]B_GDg67c:o1bb~zPphrfhlhb'`dxxRm`p.g{gZusi}oTJ^CPFGf1)Lh318827d`|t^rjt`jnfl%bb~zPcnr,a}eX{}kiRH\M^DE`64d3`dxxR~fpdnjj`)nfz~Tob~ eya\wqgsmVLXARHId2/Jj7b2ceyQiqgomkc(agySna/dz`aurngg;=S^Y?209jjvrXx`zn`d`j/hlppZehx&osoh~{inl;5f=nfz~T|d~jlhlf+lht|Vid|"g<1<2g>oi{}U{e}kciog,mkusWje{#d~31?3`?lht|Vzb|hbfnd-jjvrXkfz$e}2=>0a8mkusWyc{iagae.kmwqYdgy%b|1=11b9jjvrXx`zn`d`j/hlppZehx&c{090>c:kmwqYwayogeck ioqw[fiw'`z793?l;hlppZvnxlfbbh!fnrv\gjv(ay6=2?259jjvrXx`zn`d`j/hlppZehx&c{S=Qnne234576j2ceyQiqgomkc(agySna/hr\575?003a?lht|Vzb|hbfnd-jjvrXkfz$e}Q=229jjvrXx`zn`d`j/hlppZehx&c{S?Qnne2345433`dxxR~fpdnjj`)nfz~Tob~ iq]1[dhc89:;=?0368mkusWyc{iagae.kmwqYdgy%b|R=Paof345669k1bb~zPphrfhlhb'`dxxRm`p.ks[1443`dxxR~fpdnjj`)nfz~Tob~ iq]7[dhc89:;>95fnrv\tlvbd`dn#d`|t^alt*owW=Ujbi>?0132f>oi{}U{e}kciog,mkusWje{#d~P5318mkusWyc{iagae.kmwqYdgy%b|R;Paof34565<2ceyQiqgomkc(agySna/hr\1Zgil9:;<>5fnrv\tlvbd`dn#d`|t^alt*owW?Ujbi>?0107?lht|Vzb|hbfnd-jjvrXkfz$e}Q9_`lg456798h0ec}{_qksaioim&ceyQloq-jtZ15;2ceyQiqgomkc(agySna/hr\3Zgil9:;?03;8mkusWyc{iagae.kmwqYdgy%b|R|jg^uf[jt789:9=?74ioqw[uowmecei"gasu]`ku)nxVxnkRyj_np34564;;20ec}{_qksaioim&ceyQloq-jtZtboV}nSb|?012;6==nfz~T|d~jlhlf+lht|Vid|"g_sgd[rcXg{:;<?5fnrv\tlvbd`dn#d`|t^alt*usi}UyijQxe3;8mkusWyc{iagae.kmwqYdgy%xxlzPrde\s`Yhz9:;>338mkusWyc{iagae.kmwqYdgy%xxlzzs=31:77338mkusWyc{iagae.kmwqYdgy%xxlzzs=35:77328mkusWyc{iagae.kmwqYdgy%xxlzzs=3=64=nfz~T|d~jlhlf+lht|Vid|"}{auwp8769:81bb~zPphrfhlhb'`dxxRm`p.qweqst4;;5><5fnrv\tlvbd`dn#d`|t^alt*usi}x0?<1209jjvrXx`zn`d`j/hlppZehx&ymy{|<31=64=nfz~T|d~jlhlf+lht|Vid|"}{auwp8729:81bb~zPphrfhlhb'`dxxRm`p.qweqst4;?5><5fnrv\tlvbd`dn#d`|t^alt*usi}x0?81209jjvrXx`zn`d`j/hlppZehx&ymy{|<35=64=nfz~T|d~jlhlf+lht|Vid|"}{auwp87>9:81bb~zPphrfhlhb'`dxxRm`p.qweqst4;35>=5fnrv\tlvbd`dn#d`|t^alt*usi}x0?0=1:kmwqYwayogeck ioqw[fiw'z~jxx}331<15>oi{}U{e}kciog,mkusWje{#~znttq?748582ceyQiqgomkc(agySna/rvbppu;;78;7d`|t^rjt`jnfl%bb~zPcnr,wqgs}z6?2?>4ioqw[uowmecei"gasu]`ku)t|h~~1;1219jjvrXx`zn`d`j/hlppZehx&ymy{|<7<14>oi{}U{e}kciog,mkusWje{#~znttq?3;473`dxxR~fpdnjj`)nfz~Tob~ sucwqv:?6;:0ec}{_qksaioim&ceyQloq-ppdrr{535=k5fnrv\tlvbd`dn#d`|t^alt*usi}xS=<8;hlppZvnxlfbbh!fnrv\gjv({}ky~Q?_lw{4567:11bb~zPphrfhlhb'`dxxRm`p.qweqstW9Ufyu>?01313>oi{}U{e}kciog,mkusWje{#~znttq\4Zhh|9:;=?64ioqw[uowmecei"gasu]`ku)t|h~~R>Pnnv34576:?1bb~zPphrfhlhb'`dxxRm`p.qweqstW9Ud~=>?0358mkusWyc{iagae.kmwqYdgy%xxlzzs^2\kw6789;:j6gasu]smuckago$ec}{_bms+vrf||yT=?>4ioqw[uowmecei"gasu]`ku)t|h~~R??219jjvrXx`zn`d`j/hlppZehx&ymy{|_0314>oi{}U{e}kciog,mkusWje{#~znttq\57473`dxxR~fpdnjj`)nfz~Tob~ sucwqvY6;;:0ec}{_qksaioim&ceyQloq-ppdrr{V;?>=5fnrv\tlvbd`dn#d`|t^alt*usi}xS<;=0:kmwqYwayogeck ioqw[fiw'z~jxx}P1703?lht|Vzb|hbfnd-jjvrXkfz$yo{ur]2376>1g9jjvrXx`zn`d`j/hlppZehx&ymy{|_303?lht|Vzb|hbfnd-jjvrXkfz$yo{ur]1476>8;7d`|t^rjt`jnfl%bb~zPcnr,wqgs}zU94?>4ioqw[uowmecei"gasu]`ku)t|h~~R<6299jjvrXx`zn`d`j/hlppZehx&ymy{|_3;\jjr789;956gasu]smuckago$ec}{_bms+vrf||yT>4Qaou234475?2ceyQiqgomkc(agySna/rvbppuX:Vg~t=>?03`8mkusWyc{iagae.kmwqYdgy%xxlzzs^0\ip~789:T_Z>=7:kmwqYwayogeck ioqw[fiw'z~jxx}P2^llp5679;20ec}{_qksaioim&ceyQloq-ppdrr{V8Tbbz?01325c=nfz~T|d~jlhlf+lht|Vid|"}{auwp[6473`dxxR~fpdnjj`)nfz~Tob~ sucwqvY48;:0ec}{_qksaioim&ceyQloq-ppdrr{V9:>:5fnrv\tlvbd`dn#d`|t^alt*usi}xS>Qbuy23454e3`dxxR~fpdnjj`)nfz~Tob~ sucwqvY4Wds<=>?_RU35c=nfz~T|d~jlhlf+lht|Vid|"}{auwp[1403`dxxR~fpdnjj`)nfz~Tob~ sucwqvY3Wds<=>?299jjvrXx`zn`d`j/hlppZehx&ymy{|_5]nq}6789;9;6gasu]smuckago$ec}{_bms+vrf||yT8R``t12357>1g9jjvrXx`zn`d`j/hlppZehx&ymy{|_404?lht|Vzb|hbfnd-jjvrXkfz$yo{ur]6[hs89:;>55fnrv\tlvbd`dn#d`|t^alt*usi}xS8Qbuy234576n2ceyQiqgomkc(agySna/rvbppuX>8l0ec}{_qksaioim&ceyQloq-ppdrr{V=:j6gasu]smuckago$ec}{_bms+vrf||yT426;443`dxxR~fpdnjj`)nfz~Tob~ tdqw[wc`4895>>5fnrv\tlvbd`dn#d`|t^alt*rb{}Uyij2>4?00?lht|Vzb|hbfnd-jjvrXkfz$xh}{_sgd8439::1bb~zPphrfhlhb'`dxxRm`p.vfwqYumn6::3<<;hlppZvnxlfbbh!fnrv\gjv(|lySkh<05=66=nfz~T|d~jlhlf+lht|Vid|"zjsu]qab:607887d`|t^rjt`jnfl%bb~zPcnr,p`usW{ol0<71239jjvrXx`zn`d`j/hlppZehx&~nyQ}ef>2:75>318mkusWyc{iagae.kmwqYdgy%i~zPrde?6785;2ceyQiqgomkc(agySna/ugppZtbo5882?=4ioqw[uowmecei"gasu]`ku)smz~T~hi325<17>oi{}U{e}kciog,mkusWje{#yk|t^pfc9426;90ec}{_qksaioim&ceyQloq-wavrXzlm7>;0=3:kmwqYwayogeck ioqw[fiw'}oxxR|jg=04:75308mkusWyc{iagae.kmwqYdgy%i~zPrde?6;443`dxxR~fpdnjj`)nfz~Tob~ tdqw[wc`4::5>>5fnrv\tlvbd`dn#d`|t^alt*rb{}Uyij2<1?01?lht|Vzb|hbfnd-jjvrXkfz$xh}{_sgd8685:2ceyQiqgomkc(agySna/ugppZtbo5>5>?5fnrv\tlvbd`dn#d`|t^alt*rb{}Uyij2:>308mkusWyc{iagae.kmwqYdgy%i~zPrde?2;453`dxxR~fpdnjj`)nfz~Tob~ tdqw[wc`4>49>6gasu]smuckago$ec}{_bms+qct|Vxnk161239jjvrXx`zn`d`j/hlppZehx&~nyQ}ef>::77?5fnrv\tlvbd`dn#d`|t^alt*rb{}UyijQ>3308mkusWyc{iagae.kmwqYdgy%i~zPrde\51453`dxxR~fpdnjj`)nfz~Tob~ tdqw[wc`W8?9>6gasu]smuckago$ec}{_bms+qct|VxnkR?9239jjvrXx`zn`d`j/hlppZehx&~nyQ}ef]2374oi{}U{e}kciog,mkusWje{#yk|t^pfcZ47:;1bb~zPphrfhlhb'`dxxRm`p.vfwqYumnU9=?<4ioqw[uowmecei"gasu]`ku)smz~T~hiP2301?lht|Vzb|hbfnd-jjvrXkfz$xh}{_sgd[755:2ceyQiqgomkc(agySna/ugppZtboV8?>?5fnrv\tlvbd`dn#d`|t^alt*rb{}UyijQ=5308mkusWyc{iagae.kmwqYdgy%i~zPrde\63453`dxxR~fpdnjj`)nfz~Tob~ tdqw[wc`W;=9>6gasu]smuckago$ec}{_bms+qct|VxnkR<7239jjvrXx`zn`d`j/hlppZehx&~nyQ}ef]1=77oi{}U{e}kciog,mkusWje{#yk|t^pfcZ2592ceyQiqgomkc(agySna/ugppZtboV?9=6gasu]smuckago$ec}{_bms+qct|VxnkR8=1:kmwqYwayogeck ioqw[fiw'}oxxR|jg^515>oi{}U{e}kciog,mkusWje{#yk|t^pfcZ>592ceyQiqgomkc(agySna/ugppZtboV39>6gasu]smuckago$ec}{_bms+qct|VxnkRyj289jjvrXx`zn`d`j/hlppZehx&~nyQ}ef]taZiu89:;>o5fnrv\tlvbd`dn#d`|t^alt*rb{}UyijQxe^mq4567988i7d`|t^rjt`jnfl%bb~zPcnr,p`usW{olSzkPos234540:k1bb~zPphrfhlhb'`dxxRm`p.vfwqYumnU|iRa}012304503`dxxR~fpdnjj`)nfz~Teikloeg\vjk(E{efSc>?01]qkh6789;9=329jjvrXx`zn`d`j/hlppZocmjeoiR|`m.OqkhYi89:;Sab01235=533`dxxR~fpdnjj`)nfz~Teikloeg\vjk(E{efSc>?01]qkh6789;3=>84ioqw[uowmecei"gasu]j``ehllUyc`!Brno\j5678Vxda=>?00:\b05>3`dxxR~fpdnjj`)nfz~Teikloeg\vjk(E{efSc>?01]qkh6789;3Sk;Pru15?lht|Vzb|hbfnd-jjvrXamohcikPrno,IwijWg:;<=Q}ol23457?Wo<896gasu]smuckago$ec}{_hffgjbbW{ef#@|`m^l3456Xzfg;<=>>90303>oi{}U{e}kciog,mkusW`nnobjj_smn+HtheVd;<=>Prno34565=8;:=>;4ioqw[uowmecei"gasu]j``ehllUyc`!Brno\j5678Vxda=>?0352565?0^pli5678:8886gasu]smuckago$ec}{_hffgjbbW{ef#@|`m^l3456Xzfg;<=><2017?lht|Vzb|hbfnd-jjvrXamohcikPrno,IwijWg:;<=Q}ol234555::<0ec}{_qksaioim&ceyQfddal``Yugd%F~bcPn1234Zthe9:;<><6218mkusWyc{iagae.kmwqYnllidhhQ}ol-NvjkXf9:;5fnrv\tlvbd`dn#d`|t^kgaficmVxda"C}ol]m4566W{ef<=>?3015?lht|Vzb|hbfnd-jjvrXamohcikPrno,IwijWfzh1208mkusWyc{iagae.kmwqYnllidhhQ}ol-NvjkXgyi;Sab012367543`dxxR~fpdnjj`)nfz~Teikloeg\vjk(E{efSb~l0^pli5678;8:?;5fnrv\tlvbd`dn#d`|t^kgaficmVxda"C}ol]ltf6Xzfg;<=><1031560?04206>oi{}U{e}kciog,mkusW`nnobjj_smn+HtheVe{o=Q}ol234531;:1bb~zPphrfhlhb'`dxxRgkebmgaZthe&Gyc`Q`pb2\vjk789:>:<=:;hlppZvnxlfbbh!fnrv\macdgmoT~bc Msmn[jvd8Vxda=>?044\b0523`dxxR~fpdnjj`)nfz~Teikloeg\vjk(E{efSb~l0^pli5678<;hlppZvnxlfbbh!fnrv\macdgmoT~bc Msmn[jvd8Vxda=>?061f?lht|Vzb|hbfnd-jjvrXamohcikPrno,gqtkWfSlbz_nr1[vtdW9Ufyu>?01303>oi{}U{e}kciog,mkusW`nnobjj_smn+frudVe~xRocu^qkmcrXi{cd>l4ioqw[uowmecei"gasu]j``ehllUyc`!ltsn\kprXieTegit^cqmqnX[^;846gasu]smuckago$ec}{_hffgjbbW{ef#nz}l^mvpZgk}VycekzPrhekp4533`dxxR~fpdnjj`)nfz~Teikloeg\vjk(k}xgSb{{_bms[lht|{Unb>64ioqw[uowmecei"gasu]j``ehllUyc`!ltsn\kprXkfzTec}{r^gm[VQ7:o1bb~zPphrfhlhb'`dxxRgkebmgaZthe&i~aQ`uu]gi`kXmg987d`|t^rjt`jnfl%bb~zPieg`kacXzfg$oy|c_nww[akbeVoeS^Y?2g9jjvrXx`zn`d`j/hlppZocmjeoiR|`m.awviYh}}UoahcPwd10?lht|Vzb|hbfnd-jjvrXamohcikPrno,gqtkWfSicjm^uf[VQ6;:1bb~zPphrfhlhb'`dxxRgkebmgaZthe&i~aQ`uu]f|fcw|Voe=<=;;hlppZvnxlfbbh!fnrv\macdgmoT~bc cupo[jssWlrhi}zPeo32565oi{}U{e}kciog,mkusW`nnobjj_smn+frudVe~xRdzmq306>oi{}U{e}kciog,mkusW`nnobjj_smn+frudVe~xRdzmq]okka6;=1bb~zPphrfhlhb'`dxxRgkebmgaZthe&i~aQ`uu]iqhvXdfdl=R?<9:kmwqYwayogeck ioqw[lbbkfnnSab/bvqhZir|Vg~`R}{asv\ekb789:8m6gasu]smuckago$ec}{_hffgjbbW{ef#nz}l^mvpZkrdVymzPaof34566;j1bb~zPphrfhlhb'`dxxRgkebmgaZthe&i~aQ`uu]nqiYt|hxSl`k01235Z7392ceyQiqgomkc(agySdjjcnff[wij'j~y`Razt^qkehr5WzxhhbP0^ov|567888?=6gasu]smuckago$ec}{_hffgjbbW{ef#nz}l^mvpZuoid~9S~|lsdn\4Zkrp9:;<>;;0:kmwqYwayogeck ioqw[lbbkfnnSab/bvqhZir|Vycm`z=_rp`w`jX8Vg~t=>?0513?lht|Vzb|hbfnd-jjvrXamohcikPrno,gqtkWfSza}d3]fj62n5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohRokd^pfwZe~4949h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9949h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9849h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9;49h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9:49h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9=49h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9<49h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9?49h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9>49h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9149h6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;9049o6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[f;978o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5878o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5978o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5:78o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5;78o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5<78o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5=78o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5>78o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5?78o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5078o7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:5178h7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\g|:56;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}9576;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}9566;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}9556;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}9546;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}9536;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}9526;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}9516;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}9506;n0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}95?6;i0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]`}959:j1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^az8185k2ceyQiqgomkc(agyS`{cdht,IdbcWhnoSk|_b{?1;4d3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pcx>5:7eoi{}U{e}kciog,mkusWdghdx M`fg[dbcW{oxSnw39?0g?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\eabXzlyT`xz30?0f?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\eabXzlyT`xz311<1a>oi{}U{e}kciog,mkusWdghdx M`fg[dbcW{oxSa{{<03=6`=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZgclVxnRbzt=31:7c27;4b3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pltv?5185m2ceyQiqgomkc(agyS`{cdht,IdbcWhnoSk|_mww8439:l1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp9716;o0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]oqq:6?78n7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\hpr;9149i6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[iss4835>i5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohRokd^pfwZjr|5;5>h5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohRokd^pfwZjr|58;2?k4ioqw[uowmecei"gasu]nqibn~&GjhiQnde]qavYk}}69=3?0=e:kmwqYwayogeck ioqw[hskl`|$Aljk_`fg[wctWe0?=12d9jjvrXx`zn`d`j/hlppZkrdmc}#@okd^cg`Ztb{Vf~x1<;>3g8mkusWyc{iagae.kmwqYj}enbz"Cnde]b`aYumzUgyy2=5?0f?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\eabXzlyT`xz327<1a>oi{}U{e}kciog,mkusWdghdx M`fg[dbcW{oxSa{{<35=6`=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZgclVxnRbzt=0;:7c1=;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pltv?6;4b3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pltv?7585m2ceyQiqgomkc(agyS`{cdht,IdbcWhnoSk|_mww8679:l1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp9556;o0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]oqq:4;78n7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\hpr;;=49i6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[iss4:?5>h5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohRokd^pfwZjr|59=2?k4ioqw[uowmecei"gasu]nqibn~&GjhiQnde]qavYk}}68;3712g9jjvrXx`zn`d`j/hlppZkrdmc}#@okd^cg`Ztb{Vf~x1=6>00e?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\eabXzlyT`xz338<174=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZgclVxnRbzt=1::Z`2:m1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp959:m1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp929:m1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp939:m1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp909:m1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp919:m1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp9>9:m1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^nvp9?9:m1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^zlv969:l1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^zlv9776;o0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]{kw:6978n7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\|jt;9;49i6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[}iu4895>h5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohRokd^pfwZ~hz5;?2?k4ioqw[uowmecei"gasu]nqibn~&GjhiQnde]qavYg{6:933g8mkusWyc{iagae.kmwqYj}enbz"Cnde]b`aYumzUsc2>9?0g?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\eabXzlyTtb|31?0f?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\eabXzlyTtb|321<1a>oi{}U{e}kciog,mkusWdghdx M`fg[dbcW{oxSua}<33=6`=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZgclVxnRv`r=01:7c17;4b3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pxnp?6185m2ceyQiqgomkc(agyS`{cdht,IdbcWhnoSk|_ymq8739:l1bb~zPphrfhlhb'`dxxRczleku+HgclVkohR|js^zlv9416;o0ec}{_qksaioim&ceyQbumfjr*KflmUjhiQ}er]{kw:5?78n7d`|t^rjt`jnfl%bb~zPmtngms)JimnTmijPrdq\|jt;:149i6gasu]smuckago$ec}{_lwo`lp(EhnoSljk_sgp[}iu4;35>i5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohRokd^pfwZ~hz585>h5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohRokd^pfwZ~hz59;2?k4ioqw[uowmecei"gasu]nqibn~&GjhiQnde]qavYg{68=3=12d9jjvrXx`zn`d`j/hlppZkrdmc}#@okd^cg`Ztb{Vrd~1=;>3g8mkusWyc{iagae.kmwqYj}enbz"Cnde]b`aYumzUsc2<5?0f?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\eabXzlyTtb|337<1a>oi{}U{e}kciog,mkusWdghdx M`fg[dbcW{oxSua}<25=6`=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZgclVxnRv`r=1;:7c0=;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pxnp?7;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pxnp?0;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pxnp?1;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pxnp?2;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pxnp?3;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pxnp?<;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-NeabXimnT~h}Pxnp?=;533`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gThdxPaef3456Xkp6;2>;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qly=33:63;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qly=31:63;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qly=37:632>;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qly=35:63;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qly=3;:63:4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qly=3=70=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVnbzRokd1234Ze~4;:5?85fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^fjrZgcl9:;5?85fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^fjrZgcl9:;oi{}U{e}kciog,mkusWdghdx M`fg[vsjWmc}Sljk0123[f;;84896gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_eku[dbc89:;Snw333<00>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWmc}Sljk0123[f;;79?7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPdht\eab789:Tot2;>268mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYcaUjhi>?01]`}939;=1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aRjfv^cg`5678Vir0;0<4:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[aoqWhno<=>?_b{?3;533`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gThdxPaef3456Xkp632>:4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qly=;=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVnbzRokd1234Zjr|5;;2>o4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qcuu>24;YT_99=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPdht\eab789:T`xz310<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWmc}Sljk0123[iss4885?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^fjrZgcl9:;Pltv?5084>2ceyQiqgomkc(agyS`{cdht,IdbcWzfSigy_`fg4567We0<81379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZbn~Vkoh=>?0^nvp9706:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Ugyy2>8?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXl`|Tmij?012\hpr;904896gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_eku[dbc89:;Sa{{<0<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWmc}Sljk0123[iss4;:5?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^fjrZgcl9:;3=9;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\`lpXimn;<=>Pltv?6684>2ceyQiqgomkc(agyS`{cdht,IdbcWzfSigy_`fg4567We0?:1379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZbn~Vkoh=>?0^nvp9426:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Ugyy2=6?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXl`|Tmij?012\hpr;:>48:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_eku[dbc89:;Sa{{<3:=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVnbzRokd1234Zjr|5822>;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qcuu>1:60Pltv?7484>2ceyQiqgomkc(agyS`{cdht,IdbcWzfSigy_`fg4567We0><1379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZbn~Vkoh=>?0^nvp9546:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Ugyy2<>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYcaUjhi>?01]oqq:36:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Ugyy2:>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYcaUjhi>?01]oqq:16:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Ugyy28>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYcaUjhi>?01]oqq:?6:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Ugyy26>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYcaUjhi>?01]{kw:6879=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPdht\eab789:Ttb|310<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWmc}Sljk0123[}iu4885?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^fjrZgcl9:;Pxnp?5084>2ceyQiqgomkc(agyS`{cdht,IdbcWzfSigy_`fg4567Wqey0<81379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZbn~Vkoh=>?0^zlv9706:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Usc2>8?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXl`|Tmij?012\|jt;904896gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_eku[dbc89:;Sua}<0<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWmc}Sljk0123[}iu4;:5?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^fjrZgcl9:;3=9;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\`lpXimn;<=>Pxnp?6684>2ceyQiqgomkc(agyS`{cdht,IdbcWzfSigy_`fg4567Wqey0?:1379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZbn~Vkoh=>?0^zlv9426:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Usc2=6?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXl`|Tmij?012\|jt;:>48:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_eku[dbc89:;Sua}<3:=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVnbzRokd1234Z~hz5822>;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]gmsYflm:;<=Qwos>1:60Pxnp?7484>2ceyQiqgomkc(agyS`{cdht,IdbcWzfSigy_`fg4567Wqey0><1379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZbn~Vkoh=>?0^zlv9546:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Usc2<>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYcaUjhi>?01]{kw:36:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Usc2:>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYcaUjhi>?01]{kw:16:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Usc28>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYcaUjhi>?01]{kw:?6:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qkiw]b`a6789Usc26>268mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx9Ujhi>?01]`}969;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vir0<>1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^az8479;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vir0<<1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^az8459;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vir0<:1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^az8439;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vir0<81349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^az8419;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vir0<61349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^az84?9;=1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vir0<0<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv7Whno<=>?_b{?6584=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567Wjs7><0<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv7Whno<=>?_b{?6784=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567Wjs7>>0<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv7Whno<=>?_b{?6184=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567Wjs7>80<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv7Whno<=>?_b{?6384=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567Wjs7>:0<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv7Whno<=>?_b{?6=84=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567Wjs7>40<4:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv7Whno<=>?_b{?6;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}>Paef3456Xkp68<3=:;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tu6Ximn;<=>Pcx>05;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}>Paef3456Xkp68>3=;;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tu6Ximn;<=>Pcx>0:625?95fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs4Zgcl9:;oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz;Sljk0123[f;>79?7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq2\eab789:Tot28>268mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx9Ujhi>?01]`}9>9;=1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vir040<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv7Whno<=>?_mww8469;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vf~x1?>>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx9Ujhi>?01]oqq:6:79=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq2\eab789:T`xz312<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz;Sljk0123[iss48>5?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs4Zgcl9:;Pltv?5284>2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567We0<61379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^nvp97>6:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp1]b`a6789Ugyy2>>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx9Ujhi>?01]oqq:5879=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq2\eab789:T`xz320<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz;Sljk0123[iss4;85?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs4Zgcl9:;Pltv?6084>2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567We0?81379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^nvp9406:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp1]b`a6789Ugyy2=8?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy:Tmij?012\hpr;:04896gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr3[dbc89:;Sa{{<3<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz;Sljk0123[iss4::5?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs4Zgcl9:;3=:;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tu6Ximn;<=>Pltv?7;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}>Paef3456Xd|~783=:;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tu6Ximn;<=>Pltv?1;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}>Paef3456Xd|~7:3=:;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tu6Ximn;<=>Pltv?3;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}>Paef3456Xd|~743=:;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tu6Ximn;<=>Pltv?=;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}>Paef3456Xpfx7==0<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv7Whno<=>?_ymq8479;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vrd~1?=>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx9Ujhi>?01]{kw:6;79=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq2\eab789:Ttb|315<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz;Sljk0123[}iu48?5?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs4Zgcl9:;Pxnp?5=84>2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567Wqey0<71349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^zlv979;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~0^cg`5678Vrd~1248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx9Ujhi>?01]{kw:5979=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq2\eab789:Ttb|323<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz;Sljk0123[}iu4;95?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs4Zgcl9:;Pxnp?6384>2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~?_`fg4567Wqey0?91379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw8Vkoh=>?0^zlv94?6:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp1]b`a6789Usc2=9?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy:Tmij?012\|jt;:79=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq2\eab789:Ttb|331<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz;Sljk0123[}iu4:;5?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs4Zgcl9:;;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st5Yflm:;<=Qwos>7:632>;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st5Yflm:;<=Qwos>5:63;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st5Yflm:;<=Qwos>;:63:4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st4Yflm:;<=Qly=2=70=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{=Rokd1234Ze~48:5?85fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs5Zgcl9:;5?85fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs5Zgcl9:;oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[f;:84896gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr2[dbc89:;Snw323<01>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[f;::4896gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr2[dbc89:;Snw325<01>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[f;:<4896gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr2[dbc89:;Snw327<01>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[f;:>4896gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr2[dbc89:;Snw329<01>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[f;:04886gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr2[dbc89:;Snw32?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy;Tmij?012\g|:4879>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:Tot2<1?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy;Tmij?012\g|:4:79?7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:Tot2<>268mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]`}929;=1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~1^cg`5678Vir080<4:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv6Whno<=>?_b{?2;533`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}?Paef3456Xkp6<2>:4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st4Yflm:;<=Qly=:=71=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{=Rokd1234Ze~4048:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr2[dbc89:;Sa{{<02=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{=Rokd1234Zjr|5;:2>84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st4Yflm:;<=Qcuu>26;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}?Paef3456Xd|~7=>0<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv6Whno<=>?_mww8429;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~1^cg`5678Vf~x1?:>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]oqq:6>79=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:T`xz316<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[iss4825?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs5Zgcl9:;84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st4Yflm:;<=Qcuu>14;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}?Paef3456Xd|~7><0<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv6Whno<=>?_mww8749;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~1^cg`5678Vf~x1<<>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]oqq:5<79=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:T`xz324<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[iss4;<5?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs5Zgcl9:;Pltv?6<84=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~>_`fg4567We0?0<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv6Whno<=>?_mww8669;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~1^cg`5678Vf~x1=>>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]oqq:4:79>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:T`xz33?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy;Tmij?012\hpr;<79>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:T`xz35?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy;Tmij?012\hpr;>79>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:T`xz37?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy;Tmij?012\hpr;079>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:T`xz39?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy;Tmij?012\|jt;9948:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr2[dbc89:;Sua}<03=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{=Rokd1234Z~hz5;92>84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st4Yflm:;<=Qwos>27;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}?Paef3456Xpfx7=90<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv6Whno<=>?_ymq8439;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~1^cg`5678Vrd~1?9>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]{kw:6?79=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:Ttb|319<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[}iu4835?85fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs5Zgcl9:;84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st4Yflm:;<=Qwos>15;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}?Paef3456Xpfx7>?0<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv6Whno<=>?_ymq8759;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~1^cg`5678Vrd~1<;>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]{kw:5=79=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq3\eab789:Ttb|327<02>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz:Sljk0123[}iu4;=5?;5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs5Zgcl9:;Pxnp?6;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}?Paef3456Xpfx7?=0<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv6Whno<=>?_ymq8679;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~1^cg`5678Vrd~1==>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]{kw:46:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp0]b`a6789Usc2;>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]{kw:26:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp0]b`a6789Usc29>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]{kw:06:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp0]b`a6789Usc27>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx8Ujhi>?01]{kw:>6:>0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp3]b`a6789Uhu1>1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw:Vkoh=>?0^az8469;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vir0?0^az8449;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vir0<=1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw:Vkoh=>?0^az8429;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vir0<;1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw:Vkoh=>?0^az8409;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vir0<91349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw:Vkoh=>?0^az84>9;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vir0<71359jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw:Vkoh=>?0^az8484=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~=_`fg4567Wjs7>=0<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv5Whno<=>?_b{?6484=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~=_`fg4567Wjs7>?0<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv5Whno<=>?_b{?6684=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~=_`fg4567Wjs7>90<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv5Whno<=>?_b{?6084=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~=_`fg4567Wjs7>;0<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv5Whno<=>?_b{?6284=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~=_`fg4567Wjs7>50<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv5Whno<=>?_b{?6<84<2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~=_`fg4567Wjs7>3=:;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tu4Ximn;<=>Pcx>04;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Pcx>06;533`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}:4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qly=6=71=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{>Rokd1234Ze~4<4886gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr1[dbc89:;Snw36?17?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy8Tmij?012\g|:06:>0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp3]b`a6789Uhu161359jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw:Vkoh=>?0^az8<84>2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~=_`fg4567We0<>1379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw:Vkoh=>?0^nvp9766:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp3]b`a6789Ugyy2>2?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy8Tmij?012\hpr;9:48:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr1[dbc89:;Sa{{<06=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{>Rokd1234Zjr|5;>2>84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qcuu>22;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}?_mww84>9;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vf~x1?6>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx;Ujhi>?01]oqq:66:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp3]b`a6789Ugyy2=0?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy8Tmij?012\hpr;:848:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr1[dbc89:;Sa{{<30=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{>Rokd1234Zjr|5882>84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qcuu>10;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}80<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv5Whno<=>?_mww8709;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vf~x1<8>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx;Ujhi>?01]oqq:5079=7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq0\eab789:T`xz328<01>oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyz9Sljk0123[iss4;48:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr1[dbc89:;Sa{{<22=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{>Rokd1234Zjr|59:2>84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qcuu>06;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Pltv?0;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Pltv?2;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Pltv?<;523`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Pxnp?5584>2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~=_`fg4567Wqey0?0^zlv9756:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp3]b`a6789Usc2>3?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy8Tmij?012\|jt;9=48:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr1[dbc89:;Sua}<07=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{>Rokd1234Z~hz5;=2>84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qwos>23;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}?_ymq84?9;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vrd~1?1379jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvw:Vkoh=>?0^zlv9476:<0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp3]b`a6789Usc2=1?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy8Tmij?012\|jt;:;48:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr1[dbc89:;Sua}<31=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{>Rokd1234Z~hz58?2>84ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qwos>11;513`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|};0<6:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uv5Whno<=>?_ymq8719;?1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~2^cg`5678Vrd~1<7>248mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwx;Ujhi>?01]{kw:5179>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq0\eab789:Ttb|32?15?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxy8Tmij?012\|jt;;948:6gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr1[dbc89:;Sua}<23=73=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{>Rokd1234Z~hz5992>;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qwos>0:63;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qwos>6:63;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qwos>4:63;4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]st7Yflm:;<=Qwos>::650?17?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxyUjhi>?01]`}9766:>0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vir0<<1359jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_b{?5684<2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~Paef3456Xkp6:83=;;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tuYflm:;<=Qly=36:62oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyzTmij?012\g|:6079?7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Uhu1?6>218mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^az8484<2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~Paef3456Xkp69<3=;;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tuYflm:;<=Qly=02:62oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyzTmij?012\g|:5<79?7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Uhu1<:>268mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^az8709;=1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567Wjs7>:0<4:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uvXimn;<=>Pcx>1<;533`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Qnde2345Ydq5822>=4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]stZgcl9:;oi{}U{e}kciog,mkusWdghdx M`fg[vsjWyzTmij?012\g|:4879?7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Uhu1=>>268mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^az8649;:1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567Wjs7?3=<;hlppZvnxlfbbh!fnrv\ipjca%FmijPsto\tuYflm:;<=Qly=6=76=nfz~T|d~jlhlf+lht|Vg~`igy/Lcg`ZureVz{Sljk0123[f;=7987d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Uhu181329jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_b{?3;543`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Qnde2345Ydq525?>5fnrv\tlvbd`dn#d`|t^ovhaoq'DkohR}zm^rs[dbc89:;Snw39?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxyUjhi>?01]oqq:6879>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Ugyy2>1?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxyUjhi>?01]oqq:6:79>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Ugyy2>3?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxyUjhi>?01]oqq:6<79>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Ugyy2>5?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxyUjhi>?01]oqq:6>79>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Ugyy2>7?16?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxyUjhi>?01]oqq:6079>7d`|t^rjt`jnfl%bb~zPmtngms)JimnTxcPpq]b`a6789Ugyy2>9?17?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxyUjhi>?01]oqq:66:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vf~x1278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^nvp9466:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vf~x1<=>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^nvp9446:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vf~x1<;>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^nvp9426:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vf~x1<9>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^nvp9406:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vf~x1<7>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^nvp94>6:>0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vf~x1<1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_mww8669;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567We0>?1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_mww8649;=1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567We0>0<4:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uvXimn;<=>Pltv?0;533`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Qnde2345Yk}}6>2>:4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]stZgcl9:;4886gasu]smuckago$ec}{_lwo`lp(EhnoS~{b_qr\eab789:T`xz38?17?lht|Vzb|hbfnd-jjvrXe|foe{!Baef\wpkXxyUjhi>?01]oqq:>6:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vrd~1??>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^zlv9766:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vrd~1?=>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^zlv9746:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vrd~1?;>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^zlv9726:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vrd~1?9>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^zlv9706:?0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vrd~1?7>278mkusWyc{iagae.kmwqYj}enbz"Cnde]pqhYwxVkoh=>?0^zlv97>6:>0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vrd~1?1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_ymq8769;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567Wqey0??1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_ymq8749;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567Wqey0?=1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_ymq8729;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567Wqey0?;1349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_ymq8709;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567Wqey0?91349jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_ymq87>9;<1bb~zPphrfhlhb'`dxxRczleku+HgclVy~aR~_`fg4567Wqey0?71359jjvrXx`zn`d`j/hlppZkrdmc}#@okd^qviZvwWhno<=>?_ymq8784=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~Paef3456Xpfx7?=0<5:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uvXimn;<=>Pxnp?7484=2ceyQiqgomkc(agyS`{cdht,IdbcWzfS}~Paef3456Xpfx7??0<4:kmwqYwayogeck ioqw[hskl`|$Aljk_rwn[uvXimn;<=>Pxnp?7;533`dxxR~fpdnjj`)nfz~Taxbkiw-NeabX{|gT|}Qnde2345Yg{6?2>:4ioqw[uowmecei"gasu]nqibn~&GjhiQ|ul]stZgcl9:;?01]{kw:?6:>0ec}{_qksaioim&ceyQbumfjr*KflmUxy`Qp^cg`5678Vrd~171319jjvrXx`zn`d`j/hlppZkrdmc}#@m`uov\g|ekmViexRmv<2<06>oi{}U{e}kciog,mkusWdghdx MbmvjqYdqjfnSn`{_b{?7;76;91bb~zPphrfhlhb'`dxxRczleku+Heh}g~Totmce^ampZcvfV:8=6gasu]smuckago$ec}{_lwo`lp(Eje~byQlybnf[fhsWl{eS=?<0:kmwqYwayogeck ioqw[hskl`|$Anaznu]`}fjbWjdSha_012?lht|Vzb|hbfnd-jjvrXe|foe{!BcnwmpZe~keoToczPepl\54573`dxxR~fpdnjj`)nfz~Taxbkiw-Ngjsi|ViroakPcov\athX::>0ec}{_qksaioim&ceyQbumfjr*Kdg|dSnwlld]`jqYbygU9S^Y?359jjvrXx`zn`d`j/hlppZkrdmc}#@m`uov\g|ekmViexRk~n^0\WR4482ceyQiqgomkc(agyS`{cdht,Ifirf}Uhunbj_blw[`wiW:997d`|t^rjt`jnfl%bb~zPmtngms)JkfexRmvcmg\gkrXmxdT?RH<2:kmwqYwayogeck ioqw[hskl`|$Anaznu]`}fjbWjdSha_2]D75=nfz~T|d~jlhlf+lht|Vg~`igy/LalqkrXkpigiRmat^grjZ2492ceyQiqgomkc(agyS`{cdht,Ifirf}Uhunbj_blw[`wiW=;9j6gasu]smuckago$ec}{_lwo`lp(EdsS}~nde]lt4:768::=?h4ioqw[uowmecei"gasu]nqibn~&GfyuQp`fg[jv6494:==?=f:kmwqYwayogeck ioqw[hskl`|$A`{w_qrb`aYhx86;213d8mkusWyc{iagae.kmwqYj}enbz"Cbuy]stdbcWfz:0=0>2031b>oi{}U{e}kciog,mkusWdghdx Mlw{[uvflmUd|<2?>01257`<1<20475n2ceyQiqgomkc(agyS`{cdht,IhsWyzjhiQ`p0>3:4369;l0ec}{_qksaioim&ceyQbumfjr*Kj}qU{|ljk_nr28586>8;9j6gasu]smuckago$ec}{_lwo`lp(EdsS}~nde]lt4:768=:=?h4ioqw[uowmecei"gasu]nqibn~&GfyuQp`fg[jv6494:413d8mkusWyc{iagae.kmwqYj}enbz"Cbuy]stdbcWfz:0=0=0031b>oi{}U{e}kciog,mkusWdghdx Mlw{[uvflmUd|<2?>33357`<1<15475n2ceyQiqgomkc(agyS`{cdht,IhsWyzjhiQ`p0>3:7469;l0ec}{_qksaioim&ceyQbumfjr*Kj}qU{|ljk_nr28585;8;9j6gasu]smuckago$ec}{_lwo`lp(EdsS}~nde]lt4:76;>:=?h4ioqw[uowmecei"gasu]nqibn~&GfyuQp`fg[jv64949913d8mkusWyc{iagae.kmwqYj}enbz"Cbuy]stdbcWfz:0=0=7031b>oi{}U{e}kciog,mkusWdghdx Mlw{[uvflmUd|<2?>3:257`<1<1=475n2ceyQiqgomkc(agyS`{cdht,IhsWyzjhiQ`p0>3:6669;l0ec}{_qksaioim&ceyQbumfjr*Kj}qU{|ljk_nr2858498;9j6gasu]smuckago$ec}{_lwo`lp(EdsS}~nde]lt4:76:8:=?k4ioqw[uowmecei"gasu]nqibn~&GfyuQp`fg[jv64948?<2d9jjvrXx`zn`d`j/hlppZkrdmc}#@czx^rseabXgy;7<38>13g8mkusWyc{iagae.kmwqYj}enbz"Cbuy]stdbcWfz:0=08100f?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tugclVe{=1>18031a>oi{}U{e}kciog,mkusWdghdx Mlw{[uvflmUd|<2?>83274=nfz~T|d~jlhlf+lht|Vg~`igy/Lov|ZvwzfnT?13305>oi{}U{e}kciog,mkusWdghdx Mlw{[uvugmU;S`{w0123567492ceyQiqgomkc(agyS`{cdht,IhsWyzyciQ?_lw{45679=;8=6gasu]smuckago$ec}{_lwo`lp(EdsS}~}oe]3[hs89:;=8?<1:kmwqYwayogeck ioqw[hskl`|$A`{w_qrqkaY7Wds<=>?17305>oi{}U{e}kciog,mkusWdghdx Mlw{[uvugmU;S`{w0123527492ceyQiqgomkc(agyS`{cdht,IhsWyzyciQ?_lw{456791;8=6gasu]smuckago$ec}{_lwo`lp(EdsS}~}oe]3[hs89:;=4?<1:kmwqYwayogeck ioqw[hskl`|$A`{w_qrqkaY7Wds<=>?21305>oi{}U{e}kciog,mkusWdghdx Mlw{[uvugmU;S`{w0123647492ceyQiqgomkc(agyS`{cdht,IhsWyzyciQ?_lw{4567:;;8<6gasu]smuckago$ec}{_lwo`lp(EdsS}~}oe]3[hs89:;>>=>;hlppZvnxlfbbh!fnrv\ipjca%FaxvPpqpl`Z6Xe|r;<=>=3012?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tuthlV:Taxv?012104563`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR>Pmtz34565=89:7d`|t^rjt`jnfl%bb~zPmtngms)Je|rT|}|`d^2\ip~789:9:<=>;hlppZvnxlfbbh!fnrv\ipjca%FaxvPpqpl`Z6Xe|r;<=>=7012?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tuthlV:Taxv?0121<4563`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR>Pmtz34565189:7d`|t^rjt`jnfl%bb~zPmtngms)Je|rT|}|`d^2\ip~789:8<<=>;hlppZvnxlfbbh!fnrv\ipjca%FaxvPpqpl`Z6Xe|r;<=><1012?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tuthlV:Taxv?012064563`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR>Pmtz34564;89;7d`|t^rjt`jnfl%bb~zPmtngms)Je|rT|}|`d^2\ip~789:88>?4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[5Yj}q:;<==;1238mkusWyc{iagae.kmwqYj}enbz"Cbuy]stwicW9Ufyu>?0116567?4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[5Yj}q:;<==71238mkusWyc{iagae.kmwqYj}enbz"Cbuy]stwicW9Ufyu>?011:567:?=5fnrv\tlvbd`dn#d`|t^ovhaoq'Dg~tR~rnf\4Zkrp9:;<8?<0:kmwqYwayogeck ioqw[hskl`|$A`{w_qrqkaY7Wds<=>?6013?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tuthlV:Taxv?01245666;91bb~zPphrfhlhb'`dxxRczleku+HkrpVz{~bjP0^ov|56780;8=6gasu]smuckago$ec}{_lwo`lp(EdsS}~}oe]2[hs89:;==?<1:kmwqYwayogeck ioqw[hskl`|$A`{w_qrqkaY6Wds<=>?10304>oi{}U{e}kciog,mkusWdghdx Mlw{[uvugmU:S`{w012357563`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR?Pmtz34566:89:7d`|t^rjt`jnfl%bb~zPmtngms)Je|rT|}|`d^3\ip~789::?<=>;hlppZvnxlfbbh!fnrv\ipjca%FaxvPpqpl`Z7Xe|r;<=>>4012?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tuthlV;Taxv?012214563`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR?Pmtz34566>89:7d`|t^rjt`jnfl%bb~zPmtngms)Je|rT|}|`d^3\ip~789::;<=>;hlppZvnxlfbbh!fnrv\ipjca%FaxvPpqpl`Z7Xe|r;<=>>8012?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tuthlV;Taxv?0122=4563`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR?Pmtz34565889:7d`|t^rjt`jnfl%bb~zPmtngms)Je|rT|}|`d^3\ip~789:9=<=>;hlppZvnxlfbbh!fnrv\ipjca%FaxvPpqpl`Z7Xe|r;<=>=2013?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tuthlV;Taxv?0121767?4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[4Yj}q:;<=<:1238mkusWyc{iagae.kmwqYj}enbz"Cbuy]stwicW8Ufyu>?0105567?4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[4Yj}q:;<=<61238mkusWyc{iagae.kmwqYj}enbz"Cbuy]stwicW8Ufyu>?0113567?4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[4Yj}q:;<==<1228mkusWyc{iagae.kmwqYj}enbz"Cbuy]stwicW8Ufyu>?011774=nfz~T|d~jlhlf+lht|Vg~`igy/Lov|ZvwzfnT=Rczx1234626;81bb~zPphrfhlhb'`dxxRczleku+HkrpVz{~bjP1^ov|5678:?:?<5fnrv\tlvbd`dn#d`|t^ovhaoq'Dg~tR~rnf\5Zkrp9:;<>8>309jjvrXx`zn`d`j/hlppZkrdmc}#@czx^rsvjbX9Vg~t=>?025274=nfz~T|d~jlhlf+lht|Vg~`igy/Lov|ZvwzfnT=Rczx12346>6;81bb~zPphrfhlhb'`dxxRczleku+HkrpVz{~bjP1^ov|5678:3:?<5fnrv\tlvbd`dn#d`|t^ovhaoq'Dg~tR~rnf\5Zkrp9:;<9>>319jjvrXx`zn`d`j/hlppZkrdmc}#@czx^rsvjbX9Vg~t=>?05304>oi{}U{e}kciog,mkusWdghdx Mlw{[uvugmU:S`{w012314573`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR?Pmtz345619::0ec}{_qksaioim&ceyQbumfjr*Kj}qU{|ak_0]nq}6789=:?=5fnrv\tlvbd`dn#d`|t^ovhaoq'Dg~tR~rnf\5Zkrp9:;<5?<0:kmwqYwayogeck ioqw[hskl`|$A`{w_qrqkaY6Wds<=>?9012?lht|Vzb|hbfnd-jjvrXe|foe{!Bmtz\tuthlV8Taxv?012244563`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR>?4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[7Yj}q:;<=?=1238mkusWyc{iagae.kmwqYj}enbz"Cbuy]stwicW;Ufyu>?0130567=>?4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[7Yj}q:;<=?91238mkusWyc{iagae.kmwqYj}enbz"Cbuy]stwicW;Ufyu>?0134567?4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[7Yj}q:;<=?0102567309jjvrXx`zn`d`j/hlppZkrdmc}#@czx^rsvjbX:Vg~t=>?036274=nfz~T|d~jlhlf+lht|Vg~`igy/Lov|ZvwzfnT>Rczx1234736;81bb~zPphrfhlhb'`dxxRczleku+HkrpVz{~bjP2^ov|5678;<:?<5fnrv\tlvbd`dn#d`|t^ovhaoq'Dg~tR~rnf\6Zkrp9:;309jjvrXx`zn`d`j/hlppZkrdmc}#@czx^rsvjbX:Vg~t=>?03:274=nfz~T|d~jlhlf+lht|Vg~`igy/Lov|ZvwzfnT>Rczx12347?6;81bb~zPphrfhlhb'`dxxRczleku+HkrpVz{~bjP2^ov|5678:::?<5fnrv\tlvbd`dn#d`|t^ovhaoq'Dg~tR~rnf\6Zkrp9:;<>?>309jjvrXx`zn`d`j/hlppZkrdmc}#@czx^rsvjbX:Vg~t=>?020274=nfz~T|d~jlhlf+lht|Vg~`igy/Lov|ZvwzfnT>Rczx1234656;91bb~zPphrfhlhb'`dxxRczleku+HkrpVz{~bjP2^ov|5678:>8=6gasu]smuckago$ec}{_lwo`lp(EdsS}~}oe]1[hs89:;?9?<1:kmwqYwayogeck ioqw[hskl`|$A`{w_qrqkaY5Wds<=>?34305>oi{}U{e}kciog,mkusWdghdx Mlw{[uvugmU9S`{w0123737492ceyQiqgomkc(agyS`{cdht,IhsWyzyciQ=_lw{4567;>;8=6gasu]smuckago$ec}{_lwo`lp(EdsS}~}oe]1[hs89:;?5?<1:kmwqYwayogeck ioqw[hskl`|$A`{w_qrqkaY5Wds<=>?38305>oi{}U{e}kciog,mkusWdghdx Mlw{[uvugmU9S`{w0123057482ceyQiqgomkc(agyS`{cdht,IhsWyzyciQ=_lw{4567<89;7d`|t^rjt`jnfl%bb~zPmtngms)Je|rT|}|`d^0\ip~789:>=>>4ioqw[uowmecei"gasu]nqibn~&GfyuQpsmg[7Yj}q:;<=8>319jjvrXx`zn`d`j/hlppZkrdmc}#@czx^rsvjbX:Vg~t=>?06304>oi{}U{e}kciog,mkusWdghdx Mlw{[uvugmU9S`{w0123<4573`dxxR~fpdnjj`)nfz~Taxbkiw-Nip~XxyxdhR9:80ec}{_qksaioim&ceyQbumfjr*KugdU{~hQlooqw[4Yj}q:;<<=<;hlppZvnxlfbbh!fnrv\ipjca%F~bcPpsg\gjht|V;Taxv?013270=nfz~T|d~jlhlf+lht|Vg~`igy/LpliZvumVidb~zP1^ov|56798::?95fnrv\tlvbd`dn#d`|t^ovhaoq'DxdaR~}e^aljvrX9Vg~t=>?1032`>oi{}U{e}kciog,mkusWdghdx N022`>oi{}U{e}kciog,mkusWdghdx N202`>oi{}U{e}kciog,mkusWdghdx N262`>oi{}U{e}kciog,mkusWdghdx N242g>oi{}U{e}kciog,mkusWdghdx N73`?lht|Vzb|hbfnd-jjvrXe|foe{!A9368mkusWyc{iagae.kmwqYj}enbz"okd^ms5969:<1bb~zPphrfhlhb'`dxxRczleku+dbcWfz:0=0>249jjvrXx`zn`d`j/hlppZkrdmc}#ljk_nr28469:?1bb~zPphrfhlhb'`dxxRczleku+dbcWfz:0<>11378mkusWyc{iagae.kmwqYj}enbz"okd^ms59766;<0ec}{_qksaioim&ceyQbumfjr*gclVe{=1?>>006?lht|Vzb|hbfnd-jjvrXe|foe{!nde]lt4:6:78=7d`|t^rjt`jnfl%bb~zPmtngms)flmUd|<2>2?311>oi{}U{e}kciog,mkusWdghdx aef\ku7;9:49:6gasu]smuckago$ec}{_lwo`lp(imnTc}?312<260=nfz~T|d~jlhlf+lht|Vg~`igy/`fg[jv648>5>;5fnrv\tlvbd`dn#d`|t^ovhaoq'hnoSb~><06=5732?84ioqw[uowmecei"gasu]nqibn~&kohRa1=36:4423`dxxR~fpdnjj`)nfz~Taxbkiw-b`aYhx86::3<9;hlppZvnxlfbbh!fnrv\ipjca%jhiQ`p0>22;75=2ceyQiqgomkc(agyS`{cdht,eabXgy;7=:0=6:kmwqYwayogeck ioqw[hskl`|$mijPoq3?5286:<1bb~zPphrfhlhb'`dxxRczleku+dbcWfz:0<61279jjvrXx`zn`d`j/hlppZkrdmc}#ljk_nr284>99;?0ec}{_qksaioim&ceyQbumfjr*gclVe{=1?6>348mkusWyc{iagae.kmwqYj}enbz"okd^ms597>688?7d`|t^rjt`jnfl%bb~zPmtngms)flmUd|<2>>378mkusWyc{iagae.kmwqYj}enbz"okd^ms59799;?0ec}{_qksaioim&ceyQbumfjr*gclVe{=1348mkusWyc{iagae.kmwqYj}enbz"okd^ms5947688>7d`|t^rjt`jnfl%bb~zPmtngms)flmUd|<2=1?05?lht|Vzb|hbfnd-jjvrXe|foe{!nde]lt4:597;996gasu]smuckago$ec}{_lwo`lp(imnTc}?323<12>oi{}U{e}kciog,mkusWdghdx aef\ku7;:;4:>85fnrv\tlvbd`dn#d`|t^ovhaoq'hnoSb~><31=63=nfz~T|d~jlhlf+lht|Vg~`igy/`fg[jv64;95=?;4ioqw[uowmecei"gasu]nqibn~&kohRa1=07:7011;413`dxxR~fpdnjj`)nfz~Taxbkiw-b`aYhx86993?=5:kmwqYwayogeck ioqw[hskl`|$mijPoq3?6385>2ceyQiqgomkc(agyS`{cdht,eabXgy;7>;0>249jjvrXx`zn`d`j/hlppZkrdmc}#ljk_nr28719:?1bb~zPphrfhlhb'`dxxRczleku+dbcWfz:0?911378mkusWyc{iagae.kmwqYj}enbz"okd^ms594?6;<0ec}{_qksaioim&ceyQbumfjr*gclVe{=1<7>006?lht|Vzb|hbfnd-jjvrXe|foe{!nde]lt4:5178=7d`|t^rjt`jnfl%bb~zPmtngms)flmUd|<2=9?310>oi{}U{e}kciog,mkusWdghdx aef\ku7;:78>7d`|t^rjt`jnfl%bb~zPmtngms)flmUd|<2=>006?lht|Vzb|hbfnd-jjvrXe|foe{!nde]lt4:4878=7d`|t^rjt`jnfl%bb~zPmtngms)flmUd|<2<0?311>oi{}U{e}kciog,mkusWdghdx aef\ku7;;849:6gasu]smuckago$ec}{_lwo`lp(imnTc}?330<260=nfz~T|d~jlhlf+lht|Vg~`igy/`fg[jv64:85>;5fnrv\tlvbd`dn#d`|t^ovhaoq'hnoSb~><20=57300;75=2ceyQiqgomkc(agyS`{cdht,eabXgy;7?80=6:kmwqYwayogeck ioqw[hskl`|$mijPoq3?7086:<1bb~zPphrfhlhb'`dxxRczleku+dbcWfz:0>81279jjvrXx`zn`d`j/hlppZkrdmc}#ljk_nr286099;?0ec}{_qksaioim&ceyQbumfjr*gclVe{=1=8>348mkusWyc{iagae.kmwqYj}enbz"okd^ms5950688>7d`|t^rjt`jnfl%bb~zPmtngms)flmUd|<2<8?05?lht|Vzb|hbfnd-jjvrXe|foe{!nde]lt4:407;986gasu]smuckago$ec}{_lwo`lp(imnTc}?33?06?lht|Vzb|hbfnd-jjvrXe|foe{!nde]lt4:4688?7d`|t^rjt`jnfl%bb~zPmtngms)flmUd|<2;>378mkusWyc{iagae.kmwqYj}enbz"okd^ms59299;>0ec}{_qksaioim&ceyQbumfjr*gclVe{=1;1249jjvrXx`zn`d`j/hlppZkrdmc}#ljk_nr28086:=1bb~zPphrfhlhb'`dxxRczleku+dbcWfz:0;0=5:kmwqYwayogeck ioqw[hskl`|$mijPoq3?2;75<2ceyQiqgomkc(agyS`{cdht,eabXgy;7;3<:;hlppZvnxlfbbh!fnrv\ipjca%jhiQ`p0>4:4433`dxxR~fpdnjj`)nfz~Taxbkiw-b`aYhx8632?;4ioqw[uowmecei"gasu]nqibn~&kohRa1=:=57285fnrv\tlvbd`dn#d`|t^ovhaoq'hnoSb~><8<261=nfz~T|d~jlhlf+lht|Vg~`igy/`fg[wct494996gasu]smuckago$ec}{_lwo`lp(imnT~h}311<11>oi{}U{e}kciog,mkusWdghdx aef\v`u;984996gasu]smuckago$ec}{_lwo`lp(imnT~h}313<11>oi{}U{e}kciog,mkusWdghdx aef\v`u;9:4996gasu]smuckago$ec}{_lwo`lp(imnT~h}315<11>oi{}U{e}kciog,mkusWdghdx aef\v`u;9<4996gasu]smuckago$ec}{_lwo`lp(imnT~h}317<11>oi{}U{e}kciog,mkusWdghdx aef\v`u;9>4996gasu]smuckago$ec}{_lwo`lp(imnT~h}319<11>oi{}U{e}kciog,mkusWdghdx aef\v`u;904986gasu]smuckago$ec}{_lwo`lp(imnT~h}31?06?lht|Vzb|hbfnd-jjvrXe|foe{!nde]qav:5878>7d`|t^rjt`jnfl%bb~zPmtngms)flmUyi~2=1?06?lht|Vzb|hbfnd-jjvrXe|foe{!nde]qav:5:78>7d`|t^rjt`jnfl%bb~zPmtngms)flmUyi~2=3?06?lht|Vzb|hbfnd-jjvrXe|foe{!nde]qav:5<78>7d`|t^rjt`jnfl%bb~zPmtngms)flmUyi~2=5?06?lht|Vzb|hbfnd-jjvrXe|foe{!nde]qav:5>78>7d`|t^rjt`jnfl%bb~zPmtngms)flmUyi~2=7?06?lht|Vzb|hbfnd-jjvrXe|foe{!nde]qav:5078>7d`|t^rjt`jnfl%bb~zPmtngms)flmUyi~2=9?07?lht|Vzb|hbfnd-jjvrXe|foe{!nde]qav:56;?0ec}{_qksaioim&ceyQbumfjr*gclVxn1=?>378mkusWyc{iagae.kmwqYj}enbz"okd^pfw9566;?0ec}{_qksaioim&ceyQbumfjr*gclVxn1==>378mkusWyc{iagae.kmwqYj}enbz"okd^pfw9546;?0ec}{_qksaioim&ceyQbumfjr*gclVxn1=;>378mkusWyc{iagae.kmwqYj}enbz"okd^pfw9526;?0ec}{_qksaioim&ceyQbumfjr*gclVxn1=9>378mkusWyc{iagae.kmwqYj}enbz"okd^pfw9506;?0ec}{_qksaioim&ceyQbumfjr*gclVxn1=7>378mkusWyc{iagae.kmwqYj}enbz"okd^pfw95>6;>0ec}{_qksaioim&ceyQbumfjr*gclVxn1=1259jjvrXx`zn`d`j/hlppZkrdmc}#ljk_sgp8185<2ceyQiqgomkc(agyS`{cdht,eabXzly793<;;hlppZvnxlfbbh!fnrv\ipjca%jhiQ}er>5:7295fnrv\tlvbd`dn#d`|t^ovhaoq'hnoSk|<9<10>oi{}U{e}kciog,mkusWdghdx aef\v`u;17;m7d`|t^rjt`jnfl%bb~zPmtngms)dq5:5=k5fnrv\tlvbd`dn#d`|t^ovhaoq'js7=3?i;hlppZvnxlfbbh!fnrv\ipjca%hu1<11g9jjvrXx`zn`d`j/hlppZkrdmc}#nw33?3f?lht|Vzb|hbfnd-jjvrXe|foe{!ly^22a>oi{}U{e}kciog,mkusWdghdx cx]25`=nfz~T|d~jlhlf+lht|Vg~`igy/b{\64c348mkusWyc{iagae.kmwqYj}enbz"mvcmg\gkr;;78=7d`|t^rjt`jnfl%bb~zPmtngms)dqjfnSn`{<5<11>oi{}U{e}kciog,mkusWdghdx cxaoaZei|V:996gasu]smuckago$ec}{_lwo`lp(kpigiRmat^311>oi{}U{e}kciog,mkusWdghdx cxaoaZei|V8996gasu]smuckago$ec}{_lwo`lp(kpigiRmat^111>oi{}U{e}kciog,mkusWdghdx cxaoaZei|V>946gasu]smuckago$ec}{_lwo`lp(kpigiRmat^nlea4f3`dxxR~fpdnjj`)nfz~Taxbkiw-`}fjbWjdSaand331e>oi{}U{e}kciog,mkusWdghdx cxaoaZei|VfdmiQI2`9jjvrXx`zn`d`j/hlppZkrdmc}#nwlld]`jqYkghnTK?l4ioqw[uowmecei"gasu]nqibn~&iroakPcov\jjr789;9o6gasu]smuckago$ec}{_lwo`lp(kpigiRmat^llp567988o7d`|t^rjt`jnfl%bb~zPmtngms)dqjfnSn`{_qpfw`r;;78n7d`|t^rjt`jnfl%bb~zPmtngms)dqjfnSn`{_qpfw`r;;7;8<6gasu]smuckago$ec}{_lwo`lp(kpigiRmat^rqavcs4:4:S<=?;hlppZvnxlfbbh!fnrv\ipjca%hunbj_blw[utb{l~7?3?P2228mkusWyc{iagae.kmwqYj}enbz"mvcmg\gkrXx{oxiy2<>0]075=nfz~T|d~jlhlf+lht|Vg~`igy/b{`h`Ydf}U{~h}jt=1=5Z25:2ceyQiqgomkc(agyS`{cdht,`lpXI5:5>>5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}SL2>0?00?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]B8479::1bb~zPphrfhlhb'`dxxRczleku+aoqWH6:>3<<;hlppZvnxlfbbh!fnrv\ipjca%oe{QN<01=66=nfz~T|d~jlhlf+lht|Vg~`igy/eku[D:6<7887d`|t^rjt`jnfl%bb~zPmtngms)caUJ0<;1229jjvrXx`zn`d`j/hlppZkrdmc}#igy_@>22;443`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYF48=5>>5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}SL2>8?00?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]B84?9:;1bb~zPphrfhlhb'`dxxRczleku+aoqWH6:2?=4ioqw[uowmecei"gasu]nqibn~&nbzRO321<17>oi{}U{e}kciog,mkusWdghdx dht\E9466;90ec}{_qksaioim&ceyQbumfjr*bn~VK7>?0=3:kmwqYwayogeck ioqw[hskl`|$hdxPA=00:75318mkusWyc{iagae.kmwqYj}enbz"jfv^C?6385;2ceyQiqgomkc(agyS`{cdht,`lpXI58<2?=4ioqw[uowmecei"gasu]nqibn~&nbzRO329<17>oi{}U{e}kciog,mkusWdghdx dht\E94>6;80ec}{_qksaioim&ceyQbumfjr*bn~VK7>3<<;hlppZvnxlfbbh!fnrv\ipjca%oe{QN<22=66=nfz~T|d~jlhlf+lht|Vg~`igy/eku[D:497887d`|t^rjt`jnfl%bb~zPmtngms)caUJ0><1239jjvrXx`zn`d`j/hlppZkrdmc}#igy_@>0:74oi{}U{e}kciog,mkusWdghdx dht\EZ6592ceyQiqgomkc(agyS`{cdht,`lpXIV;9>6gasu]smuckago$ec}{_lwo`lp(l`|TMR??239jjvrXx`zn`d`j/hlppZkrdmc}#igy_@]2574oi{}U{e}kciog,mkusWdghdx dht\EZ7?:;1bb~zPphrfhlhb'`dxxRczleku+aoqWHU:5??4ioqw[uowmecei"gasu]nqibn~&nbzROP2308mkusWyc{iagae.kmwqYj}enbz"jfv^C\65453`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYFW;;9>6gasu]smuckago$ec}{_lwo`lp(l`|TMR<=239jjvrXx`zn`d`j/hlppZkrdmc}#igy_@]17745<=;hlppZvnxlfbbh!fnrv\ipjca%oe{QN_3;15>oi{}U{e}kciog,mkusWdghdx dht\EZ55:2ceyQiqgomkc(agyS`{cdht,`lpXIV9;>?5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}SLQ<1308mkusWyc{iagae.kmwqYj}enbz"jfv^C\77463`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYFW=8:7d`|t^rjt`jnfl%bb~zPmtngms)caUJS8<>;hlppZvnxlfbbh!fnrv\ipjca%oe{QN_702?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]B[2463`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYFW18:7d`|t^rjt`jnfl%bb~zPmtngms)caUJS4n5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}SLQbuy2345:4:7;9;6gasu]smuckago$ec}{_lwo`lp(l`|TMR``t12357>239jjvrXx`zn`d`j/hlppZkrdmc}#igy_L>3:75>318mkusWyc{iagae.kmwqYj}enbz"jfv^O?5785;2ceyQiqgomkc(agyS`{cdht,`lpXE5;82?=4ioqw[uowmecei"gasu]nqibn~&nbzRC315<17>oi{}U{e}kciog,mkusWdghdx dht\I9726;90ec}{_qksaioim&ceyQbumfjr*bn~VG7=;0=3:kmwqYwayogeck ioqw[hskl`|$hdxPM=34:75308mkusWyc{iagae.kmwqYj}enbz"jfv^O?5;443`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJ4;:5>>5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@2=1?00?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N8749::1bb~zPphrfhlhb'`dxxRczleku+aoqWD69?3<<;hlppZvnxlfbbh!fnrv\ipjca%oe{QB<36=66=nfz~T|d~jlhlf+lht|Vg~`igy/eku[H:5=7887d`|t^rjt`jnfl%bb~zPmtngms)caUF0?81229jjvrXx`zn`d`j/hlppZkrdmc}#igy_L>13;443`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJ4;25>>5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@2=9?01?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N8785;2ceyQiqgomkc(agyS`{cdht,`lpXE59;2?=4ioqw[uowmecei"gasu]nqibn~&nbzRC330<16>oi{}U{e}kciog,mkusWdghdx dht\I959:;1bb~zPphrfhlhb'`dxxRczleku+aoqWD6?2?<4ioqw[uowmecei"gasu]nqibn~&nbzRC35?01?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N8385:2ceyQiqgomkc(agyS`{cdht,`lpXE5=5>?5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@27>308mkusWyc{iagae.kmwqYj}enbz"jfv^O?=;463`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJW98:7d`|t^rjt`jnfl%bb~zPmtngms)caUFS<<=;hlppZvnxlfbbh!fnrv\ipjca%oe{QB_0216>oi{}U{e}kciog,mkusWdghdx dht\IZ76:;1bb~zPphrfhlhb'`dxxRczleku+aoqWDU:>?<4ioqw[uowmecei"gasu]nqibn~&nbzRCP1201?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[425:2ceyQiqgomkc(agyS`{cdht,`lpXEV;>>?5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@Q>6308mkusWyc{iagae.kmwqYj}enbz"jfv^O\52453`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJW829>6gasu]smuckago$ec}{_lwo`lp(l`|TAR?6209jjvrXx`zn`d`j/hlppZkrdmc}#igy_L]167=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HY58;80ec}{_qksaioim&ceyQbumfjr*bn~VGT><<=;hlppZvnxlfbbh!fnrv\ipjca%oe{QB_3016>oi{}U{e}kciog,mkusWdghdx dht\IZ44:;1bb~zPphrfhlhb'`dxxRczleku+aoqWDU98?<4ioqw[uowmecei"gasu]nqibn~&nbzRCP2401?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[705:2ceyQiqgomkc(agyS`{cdht,`lpXEV8<>?5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@Q=8308mkusWyc{iagae.kmwqYj}enbz"jfv^O\6<463`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJW:897d`|t^rjt`jnfl%bb~zPmtngms)caUFS>>=2:kmwqYwayogeck ioqw[hskl`|$hdxPM^1264=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HY3:81bb~zPphrfhlhb'`dxxRczleku+aoqWDU>><5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@Q9209jjvrXx`zn`d`j/hlppZkrdmc}#igy_L]464=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HY?:81bb~zPphrfhlhb'`dxxRczleku+aoqWDU2>95fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@Qa<1<11>oi{}U{e}kciog,mkusWdghdx dht\IZh;994996gasu]smuckago$ec}{_lwo`lp(l`|TAR`310<11>oi{}U{e}kciog,mkusWdghdx dht\IZh;9;4996gasu]smuckago$ec}{_lwo`lp(l`|TAR`312<11>oi{}U{e}kciog,mkusWdghdx dht\IZh;9=4996gasu]smuckago$ec}{_lwo`lp(l`|TAR`314<11>oi{}U{e}kciog,mkusWdghdx dht\IZh;9?4996gasu]smuckago$ec}{_lwo`lp(l`|TAR`316<11>oi{}U{e}kciog,mkusWdghdx dht\IZh;914996gasu]smuckago$ec}{_lwo`lp(l`|TAR`318<10>oi{}U{e}kciog,mkusWdghdx dht\IZh;978>7d`|t^rjt`jnfl%bb~zPmtngms)caUFSc2=0?06?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[k:5978>7d`|t^rjt`jnfl%bb~zPmtngms)caUFSc2=2?06?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[k:5;78>7d`|t^rjt`jnfl%bb~zPmtngms)caUFSc2=4?06?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[k:5=78>7d`|t^rjt`jnfl%bb~zPmtngms)caUFSc2=6?06?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[k:5?78>7d`|t^rjt`jnfl%bb~zPmtngms)caUFSc2=8?06?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[k:5178?7d`|t^rjt`jnfl%bb~zPmtngms)caUFSc2=>378mkusWyc{iagae.kmwqYj}enbz"jfv^O\j9576;?0ec}{_qksaioim&ceyQbumfjr*bn~VGTb1=>>368mkusWyc{iagae.kmwqYj}enbz"jfv^O\j959:=1bb~zPphrfhlhb'`dxxRczleku+aoqWDUe090=4:kmwqYwayogeck ioqw[hskl`|$hdxPM^l?1;433`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJWg6=2?:4ioqw[uowmecei"gasu]nqibn~&nbzRCPn=5=61=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HYi414986gasu]smuckago$ec}{_lwo`lp(l`|TAR`39?00?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[kY7::1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS<<;;hlppZvnxlfbbh!fnrv\ipjca%oe{QB_o]247295fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@Qa_0010>oi{}U{e}kciog,mkusWdghdx dht\IZhX9:8?7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQ>4368mkusWyc{iagae.kmwqYj}enbz"jfv^O\jZ72:=1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS<8=4:kmwqYwayogeck ioqw[hskl`|$hdxPM^l\52433`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJWgU:4?:4ioqw[uowmecei"gasu]nqibn~&nbzRCPn^3:66=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HYiW;8?7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQ=0368mkusWyc{iagae.kmwqYj}enbz"jfv^O\jZ46:=1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS?<=4:kmwqYwayogeck ioqw[hskl`|$hdxPM^l\66433`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJWgU98?:4ioqw[uowmecei"gasu]nqibn~&nbzRCPn^0661=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HYiW;<986gasu]smuckago$ec}{_lwo`lp(l`|TAR`P2607?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[kY50;>0ec}{_qksaioim&ceyQbumfjr*bn~VGTbR<6229jjvrXx`zn`d`j/hlppZkrdmc}#igy_L]m[6433`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJWgU8>5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@Qa_900?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[kY>:j1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS`{w01228585l2ceyQiqgomkc(agyS`{cdht,`lpXEVdTaxv?013?4;75l2ceyQiqgomkc(agyS`{cdht,`lpXEVdTaxv?013?5585m2ceyQiqgomkc(agyS`{cdht,`lpXEVdTaxv?013?5586:m1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS`{w01228479:l1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS`{w012284799;n0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx12359756;o0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx1235975688o7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQbuy2344:6;78n7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQbuy2344:6;7;9h6gasu]smuckago$ec}{_lwo`lp(l`|TAR`Pmtz3457;9=49i6gasu]smuckago$ec}{_lwo`lp(l`|TAR`Pmtz3457;9=4:>i5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@Qa_lw{456648?5>h5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S@Qa_lw{456648?5=?j4ioqw[uowmecei"gasu]nqibn~&nbzRCPn^ov|56795;=2?k4ioqw[uowmecei"gasu]nqibn~&nbzRCPn^ov|56795;=2<2e9jjvrXx`zn`d`j/hlppZkrdmc}#igy_L]m[hs89::0<712d9jjvrXx`zn`d`j/hlppZkrdmc}#igy_L]m[hs89::0<7113a8mkusWyc{iagae.kmwqYj}enbz"jfv^O\jZkrp9:;=1?12e9jjvrXx`zn`d`j/hlppZkrdmc}#igy_L]m[hs89::0<0>2e9jjvrXx`zn`d`j/hlppZkrdmc}#igy_L]m[hs89::0?>12d9jjvrXx`zn`d`j/hlppZkrdmc}#igy_L]m[hs89::0?>113f8mkusWyc{iagae.kmwqYj}enbz"jfv^O\jZkrp9:;=1<>>3g8mkusWyc{iagae.kmwqYj}enbz"jfv^O\jZkrp9:;=1<>>00g?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[kYj}q:;<<2=2?0f?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]N[kYj}q:;<<2=2?31`>oi{}U{e}kciog,mkusWdghdx dht\IZhXe|r;<=?322<1a>oi{}U{e}kciog,mkusWdghdx dht\IZhXe|r;<=?322<26a=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HYiWds<=>><36=6`=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HYiWds<=>><36=57b?1=06:7c?1=06:44c3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJWgUfyu>?00>12;4b3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJWgUfyu>?00>12;75l2ceyQiqgomkc(agyS`{cdht,`lpXEVdTaxv?013?6285m2ceyQiqgomkc(agyS`{cdht,`lpXEVdTaxv?013?6286:m1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS`{w012287>9:l1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS`{w012287>99;n0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx123594>6;o0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx123594>688h7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQbuy2344:56;n0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx12359499;n0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx12359576;o0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx1235957688o7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQbuy2344:4978n7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQbuy2344:497;9o6gasu]smuckago$ec}{_lwo`lp(l`|TAR`Pmtz3457;;78o7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQbuy2344:4688h7d`|t^rjt`jnfl%bb~zPmtngms)caUFScQbuy2344:36;n0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx12359299;i0ec}{_qksaioim&ceyQbumfjr*bn~VGTbRczx1235939:m1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS`{w01228086:j1bb~zPphrfhlhb'`dxxRczleku+aoqWDUeS`{w01228385l2ceyQiqgomkc(agyS`{cdht,`lpXEVdTaxv?013?2;75k2ceyQiqgomkc(agyS`{cdht,`lpXEVdTaxv?013?3;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJWgUfyu>?00>4:44d3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYJWgUfyu>?00>;:7b?1=:=57e?1=;=6a=nfz~T|d~jlhlf+lht|Vg~`igy/eku[HYiWds<=>><8<267=nfz~T|d~jlhlf+lht|Vg~`igy/eku[T:76;90ec}{_qksaioim&ceyQbumfjr*bn~V[7==0=3:kmwqYwayogeck ioqw[hskl`|$hdxPQ=32:75318mkusWyc{iagae.kmwqYj}enbz"jfv^S?5185;2ceyQiqgomkc(agyS`{cdht,`lpXY5;>2?=4ioqw[uowmecei"gasu]nqibn~&nbzR_317<17>oi{}U{e}kciog,mkusWdghdx dht\U9706;90ec}{_qksaioim&ceyQbumfjr*bn~V[7=50=3:kmwqYwayogeck ioqw[hskl`|$hdxPQ=3::741229jjvrXx`zn`d`j/hlppZkrdmc}#igy_P>15;443`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYV4;85>>5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\2=3?00?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]R8729::1bb~zPphrfhlhb'`dxxRczleku+aoqWX6993<<;hlppZvnxlfbbh!fnrv\ipjca%oe{Q^<34=66=nfz~T|d~jlhlf+lht|Vg~`igy/eku[T:5?7887d`|t^rjt`jnfl%bb~zPmtngms)caUZ0?61229jjvrXx`zn`d`j/hlppZkrdmc}#igy_P>1=;453`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYV4;49?6gasu]smuckago$ec}{_lwo`lp(l`|T]1=?>318mkusWyc{iagae.kmwqYj}enbz"jfv^S?7485:2ceyQiqgomkc(agyS`{cdht,`lpXY595>?5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\2;>308mkusWyc{iagae.kmwqYj}enbz"jfv^S?1;453`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYV4?49>6gasu]smuckago$ec}{_lwo`lp(l`|T]191239jjvrXx`zn`d`j/hlppZkrdmc}#igy_P>;:74;hlppZvnxlfbbh!fnrv\ipjca%oe{Q^_001?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]R[465:2ceyQiqgomkc(agyS`{cdht,`lpXYV;:>?5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\Q>2308mkusWyc{iagae.kmwqYj}enbz"jfv^S\56453`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYVW8>9>6gasu]smuckago$ec}{_lwo`lp(l`|T]R?:239jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]2274897d`|t^rjt`jnfl%bb~zPmtngms)caUZS<6=2:kmwqYwayogeck ioqw[hskl`|$hdxPQ^3:64=nfz~T|d~jlhlf+lht|Vg~`igy/eku[TY5:;1bb~zPphrfhlhb'`dxxRczleku+aoqWXU9?5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\Q=4308mkusWyc{iagae.kmwqYj}enbz"jfv^S\60453`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYVW;<9>6gasu]smuckago$ec}{_lwo`lp(l`|T]R<8239jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]1<74<=;hlppZvnxlfbbh!fnrv\ipjca%oe{Q^_2216>oi{}U{e}kciog,mkusWdghdx dht\UZ56:81bb~zPphrfhlhb'`dxxRczleku+aoqWXU?><5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\Q:209jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]564=nfz~T|d~jlhlf+lht|Vg~`igy/eku[TY0:81bb~zPphrfhlhb'`dxxRczleku+aoqWXU3><5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\Q62`9jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]nq}67896;2?l4ioqw[uowmecei"gasu]nqibn~&nbzR_Pmtz3456;87;9n6gasu]smuckago$ec}{_lwo`lp(l`|T]Rczx12349776;i0ec}{_qksaioim&ceyQbumfjr*bn~V[Taxv?012?5586:k1bb~zPphrfhlhb'`dxxRczleku+aoqWXUfyu>?01>25;4d3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYVWds<=>?<03=57d313<1g>oi{}U{e}kciog,mkusWdghdx dht\UZkrp9:;<1?=>00a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]R[hs89:;0<=12b9jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]nq}67896:?3?=b:kmwqYwayogeck ioqw[hskl`|$hdxPQ^ov|56785;?2?m4ioqw[uowmecei"gasu]nqibn~&nbzR_Pmtz3456;9=4:>o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\Qbuy2345:6=78h7d`|t^rjt`jnfl%bb~zPmtngms)caUZS`{w012384399;h0ec}{_qksaioim&ceyQbumfjr*bn~V[Taxv?012?5385k2ceyQiqgomkc(agyS`{cdht,`lpXYVg~t=>?0=35:44e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYVWds<=>?<05=6f=nfz~T|d~jlhlf+lht|Vg~`igy/eku[TYj}q:;<=2>7?31f>oi{}U{e}kciog,mkusWdghdx dht\UZkrp9:;<1?7>3a8mkusWyc{iagae.kmwqYj}enbz"jfv^S\ip~789:7=50>2c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]nq}67896:53?01>14;4d3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYVWds<=>?<32=57d320<1g>oi{}U{e}kciog,mkusWdghdx dht\UZkrp9:;<1<>>00a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]R[hs89:;0?<12b9jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]nq}678969>3?=b:kmwqYwayogeck ioqw[hskl`|$hdxPQ^ov|56785882?m4ioqw[uowmecei"gasu]nqibn~&nbzR_Pmtz3456;::4:>o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\Qbuy2345:5<78h7d`|t^rjt`jnfl%bb~zPmtngms)caUZS`{w012387299;h0ec}{_qksaioim&ceyQbumfjr*bn~V[Taxv?012?6085k2ceyQiqgomkc(agyS`{cdht,`lpXYVg~t=>?0=06:44e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYVWds<=>?<34=6f=nfz~T|d~jlhlf+lht|Vg~`igy/eku[TYj}q:;<=2=6?31f>oi{}U{e}kciog,mkusWdghdx dht\UZkrp9:;<1<8>3a8mkusWyc{iagae.kmwqYj}enbz"jfv^S\ip~789:7>:0>2c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]nq}67896943688j7d`|t^rjt`jnfl%bb~zPmtngms)caUZS`{w01238785j2ceyQiqgomkc(agyS`{cdht,`lpXYVg~t=>?0=0=57d331<1g>oi{}U{e}kciog,mkusWdghdx dht\UZkrp9:;<1=?>00a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]R[hs89:;0>?12b9jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]nq}678968=3?=a:kmwqYwayogeck ioqw[hskl`|$hdxPQ^ov|5678595>o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\Qbuy2345:4688j7d`|t^rjt`jnfl%bb~zPmtngms)caUZS`{w01238185j2ceyQiqgomkc(agyS`{cdht,`lpXYVg~t=>?0=6=57g35?0a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]R[hs89:;080>2`9jjvrXx`zn`d`j/hlppZkrdmc}#igy_P]nq}67896=2?l4ioqw[uowmecei"gasu]nqibn~&nbzR_Pmtz3456;>7;9m6gasu]smuckago$ec}{_lwo`lp(l`|T]Rczx1234919:k1bb~zPphrfhlhb'`dxxRczleku+aoqWXUfyu>?01>4:44f3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYVWds<=>?<9<1f>oi{}U{e}kciog,mkusWdghdx dht\UZkrp9:;<16113c8mkusWyc{iagae.kmwqYj}enbz"jfv^S\ip~789:753:5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}S\Qaou23474?3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYVWge<=>=1378mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ze~a;=0ec}{_qksaioim&ceyQbumfjr*bn~VkohRmvi321f>oi{}U{e}kciog,mkusWdghdx dht\eabXkpc9oi{}U{e}kciog,mkusWdghdx dht\eabXkpc>S^Y>269jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[fn>>837d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>3:7?103;8mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ziw95:5=?o4ioqw[uowmecei"gasu]nqibn~&nbzRokd^ms5969988j7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>3:145i2ceyQiqgomkc(agyS`{cdht,`lpXimnTc}?30?416<=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<>12c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv648:5=<9>o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28469>;8m7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>24;05WZ]:>45fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28479:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><03=544e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2>1?616g=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:09>o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28449>;8m7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>26;05WZ]:>45fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28459:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><01=544e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2>3?616g=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<=1630e?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx86:?38=_RU26<=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<:12c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv648>5=<9>o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28429>;8m7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>20;05WZ]:>45fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28439:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><07=544e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2>5?616g=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<;1630e?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx86:938=_RU26<=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<812c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv648<5=<7>9>o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28409>;8m7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>22;05WZ]:>45fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28419:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><05=544e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2>7?616g=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<91630e?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx86:;38=_RU26<=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<612c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv64825=<9>o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr284>9>;8m7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>2<;05WZ]:>45fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr284?9:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><0;=544e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2>9?616g=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<71630e?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx86:538=_RU26==nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<0=9:kmwqYwayogeck ioqw[hskl`|$hdxPaef\ku7;97:956gasu]smuckago$ec}{_lwo`lp(l`|TmijPoq3?5;75i2ceyQiqgomkc(agyS`{cdht,`lpXimnTc}?31?326d=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0<0;23c8mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ziw95;5:?<6;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]lt4:5878i7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>14;76:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><32=074e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=0?416c=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0?>163]PS54>3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=1?0a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx869=3?>2c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv64;;58?k5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28779>;UX[=<6;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]lt4:5:78i7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>16;76:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><30=074e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=2?416c=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0?<163]PS54>3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=3?0a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx869?3?>2c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv64;958?k5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28759>;UX[=<6;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]lt4:5<78i7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>10;76:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><36=074e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=4?416c=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0?:163]PS54>3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=5?0a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx86993?>2c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv64;?58?k5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28739>;UX[=<6;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]lt4:5>78i7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>12;76:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><34=074e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=6?416c=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0?8163]PS54>3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=7?0a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx869;3?>2c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv64;=58?k5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28719>;UX[=<6;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]lt4:5078i7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>1<;76:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><3:=074e3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=8?416c=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0?6163]PS54>3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2=9?0a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx86953?>2c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv64;358?k5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr287?9>;UX[=<7;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]lt4:56;30ec}{_qksaioim&ceyQbumfjr*bn~VkohRa1=0=47?<22=6g=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0>>1100a?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx868<3:=2c9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv64::5:?o5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28679988i7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>05;25:k1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><23=274a3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<2<1?41[VQ7:l1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><20=[hgil;20ec}{_qksaioim&ceyQbumfjr*bn~VkohRa1=1=6d=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0>0>13c8mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ziw95958?55fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr28185i2ceyQiqgomkc(agyS`{cdht,`lpXimnTc}?34?326d=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:090;23c8mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ziw95>5:?=8:kmwqYwayogeck ioqw[hskl`|$hdxPaef\ku7;=78j7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>6:475i2ceyQiqgomkc(agyS`{cdht,`lpXimnTc}?35?616d=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:080923g8mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ziw95?5:?Q\W10;?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx86=2?o4ioqw[uowmecei"gasu]nqibn~&nbzRokd^ms5909988j7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>5:145i2ceyQiqgomkc(agyS`{cdht,`lpXimnTc}?36?416`=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz:0;092^QT47>4:=?o4ioqw[uowmecei"gasu]nqibn~&nbzRokd^ms5919<;8j7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>4:345m2ceyQiqgomkc(agyS`{cdht,`lpXimnTc}?37?41[VQ6:11bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~><9<1e>oi{}U{e}kciog,mkusWdghdx dht\eabXgy;743?>2`9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv6414?>?o4ioqw[uowmecei"gasu]nqibn~&nbzRokd^ms59>9>;8n7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p0>;:34X[^;946gasu]smuckago$ec}{_lwo`lp(l`|TmijPoq3?=;4f3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|<26>031e>oi{}U{e}kciog,mkusWdghdx dht\eabXgy;753:=2`9jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv6404=>?k4ioqw[uowmecei"gasu]nqibn~&nbzRokd^ms59?9>;UX[<3:675k2ceyQiqgomkc(agyS`{cdht,`lpXimnTc}<30?12[44b3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|?2>0?3\WR6512ceyQiqgomkc(agyS`{cdht,`lpXimnTc}<310<1e>oi{}U{e}kciog,mkusWdghdx dht\eabXgy87=<0>289jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv54885>l5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr184499;30ec}{_qksaioim&ceyQbumfjr*bn~VkohRa2=30:7g1?<>00:?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx;6:833`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|?2>8?0b?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx;6:43?=9:kmwqYwayogeck ioqw[hskl`|$hdxPaef\ku4;9049m6gasu]smuckago$ec}{_lwo`lp(l`|TmijPoq0?5<86:m1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~=<0<2[VQ7:01bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~=<32=6d=nfz~T|d~jlhlf+lht|Vg~`igy/eku[dbcWfz90?>113;8mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ziw:58:2?o4ioqw[uowmecei"gasu]nqibn~&nbzRokd^ms694668827d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p3>16;4f3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUd|?2=2?31=>oi{}U{e}kciog,mkusWdghdx dht\eabXgy87>>0=a:kmwqYwayogeck ioqw[hskl`|$hdxPaef\ku4;::4:>45fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr18729:h1bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSb~=<36=57?1<:>3c8mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ziw:58>2<<6;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]lt7:5>78j7d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ`p3>12;7512ceyQiqgomkc(agyS`{cdht,`lpXimnTc}<326<1e>oi{}U{e}kciog,mkusWdghdx dht\eabXgy87>:0>289jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv54;25>l5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr187>99;30ec}{_qksaioim&ceyQbumfjr*bn~VkohRa2=0::7g1<6>00g?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx;692<1299jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv54:4956gasu]smuckago$ec}{_lwo`lp(l`|TmijPoq0?7;7502ceyQiqgomkc(agyS`{cdht,`lpXimnTc}<34?0:?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYhx;6?2<<7;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]lt7:26;30ec}{_qksaioim&ceyQbumfjr*bn~VkohRa2=7=57>181289jjvrXx`zn`d`j/hlppZkrdmc}#igy_`fg[jv54?4:>i5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr18286WZ];>i5fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_nr18=86WZ];>55fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_sgp858512ceyQiqgomkc(agyS`{cdht,`lpXimnT~h}311<1=>oi{}U{e}kciog,mkusWdghdx dht\eabXzly7=<0=9:kmwqYwayogeck ioqw[hskl`|$hdxPaef\v`u;9;4956gasu]smuckago$ec}{_lwo`lp(l`|TmijPrdq?568512ceyQiqgomkc(agyS`{cdht,`lpXimnT~h}315<1=>oi{}U{e}kciog,mkusWdghdx dht\eabXzly7=80=9:kmwqYwayogeck ioqw[hskl`|$hdxPaef\v`u;9?4956gasu]smuckago$ec}{_lwo`lp(l`|TmijPrdq?528512ceyQiqgomkc(agyS`{cdht,`lpXimnT~h}319<1=>oi{}U{e}kciog,mkusWdghdx dht\eabXzly7=40=8:kmwqYwayogeck ioqw[hskl`|$hdxPaef\v`u;97827d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ}er>14;4>3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUyi~2=1?0:?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYumz69>3<6;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]qav:5;7827d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ}er>10;4>3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUyi~2=5?0:?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYumz69:3<6;hlppZvnxlfbbh!fnrv\ipjca%oe{Qnde]qav:5?7827d`|t^rjt`jnfl%bb~zPmtngms)caUjhiQ}er>1<;4>3`dxxR~fpdnjj`)nfz~Taxbkiw-gmsYflmUyi~2=9?0;?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYumz692?74ioqw[uowmecei"gasu]nqibn~&nbzRokd^pfw9576;30ec}{_qksaioim&ceyQbumfjr*bn~VkohR|js=12:7?3:8mkusWyc{iagae.kmwqYj}enbz"jfv^cg`Ztb{595>55fnrv\tlvbd`dn#d`|t^ovhaoq'mc}Sljk_sgp818502ceyQiqgomkc(agyS`{cdht,`lpXimnT~h}35?0;?lht|Vzb|hbfnd-jjvrXe|foe{!kiw]b`aYumz6=2?64ioqw[uowmecei"gasu]nqibn~&nbzRokd^pfw919:11bb~zPphrfhlhb'`dxxRczleku+aoqWhnoSk|<9<1<>oi{}U{e}kciog,mkusWdghdx dht\eabXzly7532:74368mkusWyc{iagae.kmwqYj}enbz"~_nr28586:=1bb~zPphrfhlhb'`dxxRczleku+uvXgy;7==0=5:kmwqYwayogeck ioqw[hskl`|$|}Q`p0>24;75<2ceyQiqgomkc(agyS`{cdht,tuYhx86:=3<:;hlppZvnxlfbbh!fnrv\ipjca%{|Ra1=32:4433`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw95;92?;4ioqw[uowmecei"gasu]nqibn~&z{Sb~><00=57285fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?312<261=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku7;9=4996gasu]smuckago$ec}{_lwo`lp(xyUd|<2>4?310>oi{}U{e}kciog,mkusWdghdx pq]lt4:6=78>7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=1?:>007?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms59716;?0ec}{_qksaioim&ceyQbumfjr*vwWfz:0<811368mkusWyc{iagae.kmwqYj}enbz"~_nr28419:<1bb~zPphrfhlhb'`dxxRczleku+uvXgy;7=:0>259jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq3?5=85=2ceyQiqgomkc(agyS`{cdht,tuYhx86:43?=4:kmwqYwayogeck ioqw[hskl`|$|}Q`p0>2=;423`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw95;22<<<;hlppZvnxlfbbh!fnrv\ipjca%{|Ra1=3=61=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku7;97;986gasu]smuckago$ec}{_lwo`lp(xyUd|<2=0?06?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms5947688?7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=1<>>378mkusWyc{iagae.kmwqYj}enbz"~_nr287799;>0ec}{_qksaioim&ceyQbumfjr*vwWfz:0?<1249jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq3?6786:=1bb~zPphrfhlhb'`dxxRczleku+uvXgy;7>>0=5:kmwqYwayogeck ioqw[hskl`|$|}Q`p0>17;75<2ceyQiqgomkc(agyS`{cdht,tuYhx86983<:;hlppZvnxlfbbh!fnrv\ipjca%{|Ra1=07:4433`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw958>2?;4ioqw[uowmecei"gasu]nqibn~&z{Sb~><37=57285fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?327<261=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku7;:>4996gasu]smuckago$ec}{_lwo`lp(xyUd|<2=7?310>oi{}U{e}kciog,mkusWdghdx pq]lt4:5078>7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=1<7>007?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms594>6;?0ec}{_qksaioim&ceyQbumfjr*vwWfz:0?711318mkusWyc{iagae.kmwqYj}enbz"~_nr28785<2ceyQiqgomkc(agyS`{cdht,tuYhx8692<<;;hlppZvnxlfbbh!fnrv\ipjca%{|Ra1=13:73<23=60=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku7;;84:>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?33?07?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms59599;90ec}{_qksaioim&ceyQbumfjr*vwWfz:090=4:kmwqYwayogeck ioqw[hskl`|$|}Q`p0>7:4443`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw95?5>95fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?35?317>oi{}U{e}kciog,mkusWdghdx pq]lt4:16;>0ec}{_qksaioim&ceyQbumfjr*vwWfz:0;0>229jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq3?3;433`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw95=5=?=4ioqw[uowmecei"gasu]nqibn~&z{Sb~><9<10>oi{}U{e}kciog,mkusWdghdx pq]lt4:?68887d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=171259jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq3?=;75=2ceyQiqgomkc(agyS`{cdht,tuYhx8Uy0=0=6:kmwqYwayogeck ioqw[hskl`|$|}Q`p0]q8469:?1bb~zPphrfhlhb'`dxxRczleku+uvXgy;T~1?>>348mkusWyc{iagae.kmwqYj}enbz"~_nr2[w:6:78=7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=R|312<12>oi{}U{e}kciog,mkusWdghdx pq]lt4Yu48>5>;5fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?Pr=36:702ceyQiqgomkc(agyS`{cdht,tuYhx8Uy0<61279jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq3\v97>6;?0ec}{_qksaioim&ceyQbumfjr*vwWfz:S2>>348mkusWyc{iagae.kmwqYj}enbz"~_nr2[w:5878=7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=R|320<12>oi{}U{e}kciog,mkusWdghdx pq]lt4Yu4;85>;5fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?Pr=00:702ceyQiqgomkc(agyS`{cdht,tuYhx8Uy0?81279jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq3\v9406;<0ec}{_qksaioim&ceyQbumfjr*vwWfz:S2=8?05?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms5Zt;:04996gasu]smuckago$ec}{_lwo`lp(xyUd|oi{}U{e}kciog,mkusWdghdx pq]lt4Yu4::5>;5fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?Pr=12:73_s>7:732?;4ioqw[uowmecei"gasu]nqibn~&z{Sb~>_s>5:73_s>;:73_s]361=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku7XzV;996gasu]smuckago$ec}{_lwo`lp(xyUd|oi{}U{e}kciog,mkusWdghdx pq]lt4YuW8;996gasu]smuckago$ec}{_lwo`lp(xyUd|oi{}U{e}kciog,mkusWdghdx pq]lt4YuW89996gasu]smuckago$ec}{_lwo`lp(xyUd|oi{}U{e}kciog,mkusWdghdx pq]lt4YuW8?996gasu]smuckago$ec}{_lwo`lp(xyUd|oi{}U{e}kciog,mkusWdghdx pq]lt4YuW8=996gasu]smuckago$ec}{_lwo`lp(xyUd|oi{}U{e}kciog,mkusWdghdx pq]lt4YuW83986gasu]smuckago$ec}{_lwo`lp(xyUd|7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=R|P2006?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms5ZtX:;8>7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=R|P2206?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms5ZtX:=8>7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=R|P2406?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms5ZtX:?8>7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=R|P2606?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms5ZtX:18>7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{=R|P2807?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms5ZtX;;?0ec}{_qksaioim&ceyQbumfjr*vwWfz:SQ<0378mkusWyc{iagae.kmwqYj}enbz"~_nr2[wY49;>0ec}{_qksaioim&ceyQbumfjr*vwWfz:SQ;259jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq3\vZ35<2ceyQiqgomkc(agyS`{cdht,tuYhx8UyS;<;;hlppZvnxlfbbh!fnrv\ipjca%{|Ra1^p\37295fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?Pr^;17>oi{}U{e}kciog,mkusWdghdx pq]lt7:76;>0ec}{_qksaioim&ceyQbumfjr*vwWfz90=0>259jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq0?5585=2ceyQiqgomkc(agyS`{cdht,tuYhx;6:<3?=4:kmwqYwayogeck ioqw[hskl`|$|}Q`p3>25;423`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw:5;:2<<;;hlppZvnxlfbbh!fnrv\ipjca%{|Ra2=31:7395fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}<315<11>oi{}U{e}kciog,mkusWdghdx pq]lt7:6<7;986gasu]smuckago$ec}{_lwo`lp(xyUd|?2>5?06?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms6972688?7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{>1?9>378mkusWyc{iagae.kmwqYj}enbz"~_nr184099;>0ec}{_qksaioim&ceyQbumfjr*vwWfz90<91249jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq0?5286:=1bb~zPphrfhlhb'`dxxRczleku+uvXgy87=50=5:kmwqYwayogeck ioqw[hskl`|$|}Q`p3>2<;75<2ceyQiqgomkc(agyS`{cdht,tuYhx;6:53<:;hlppZvnxlfbbh!fnrv\ipjca%{|Ra2=3::4443`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw:5;5>95fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}<31?310>oi{}U{e}kciog,mkusWdghdx pq]lt7:5878>7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{>1007?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms69466;?0ec}{_qksaioim&ceyQbumfjr*vwWfz90??11368mkusWyc{iagae.kmwqYj}enbz"~_nr18749:<1bb~zPphrfhlhb'`dxxRczleku+uvXgy87>?0>259jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq0?6685=2ceyQiqgomkc(agyS`{cdht,tuYhx;69?3?=4:kmwqYwayogeck ioqw[hskl`|$|}Q`p3>10;423`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw:58?2<<;;hlppZvnxlfbbh!fnrv\ipjca%{|Ra2=06:7395fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}<326<11>oi{}U{e}kciog,mkusWdghdx pq]lt7:5?7;986gasu]smuckago$ec}{_lwo`lp(xyUd|?2=8?06?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms694?688?7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{>1<6>378mkusWyc{iagae.kmwqYj}enbz"~_nr187?99;90ec}{_qksaioim&ceyQbumfjr*vwWfz90?0=4:kmwqYwayogeck ioqw[hskl`|$|}Q`p3>1:4433`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw:59;2?;4ioqw[uowmecei"gasu]nqibn~&z{Sb~=<22=57285fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}<330<266=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku4;;78?7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{>1=11318mkusWyc{iagae.kmwqYj}enbz"~_nr18185<2ceyQiqgomkc(agyS`{cdht,tuYhx;6?2<<<;hlppZvnxlfbbh!fnrv\ipjca%{|Ra2=7=61=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku4;=7;9?6gasu]smuckago$ec}{_lwo`lp(xyUd|?29>368mkusWyc{iagae.kmwqYj}enbz"~_nr18386::1bb~zPphrfhlhb'`dxxRczleku+uvXgy87;3<;;hlppZvnxlfbbh!fnrv\ipjca%{|Ra2=5=575000?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms69?9:=1bb~zPphrfhlhb'`dxxRczleku+uvXgy8753?=6:kmwqYwayogeck ioqw[hskl`|$|}Q`p3]q[5Y7:?1bb~zPphrfhlhb'`dxxRczleku+uvXgy8T~R>P1348mkusWyc{iagae.kmwqYj}enbz"~_nr1[wY7W;8=7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{>R|P0^112>oi{}U{e}kciog,mkusWdghdx pq]lt7YuW9U?>;5fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}1319jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq0\vZ6Xe|r;<=>30?31b>oi{}U{e}kciog,mkusWdghdx pq]lt7YuW9Ufyu>?01>2:66Pmtz3456;:79;7d`|t^rjt`jnfl%bb~zPmtngms)wxVe{>R|P0^ov|5678585=?h4ioqw[uowmecei"gasu]nqibn~&z{Sb~=_s]3[hs89:;0>0<0:kmwqYwayogeck ioqw[hskl`|$|}Q`p3]q[5Yj}q:;<=2<>00e?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms6ZtX8Vg~t=>?0=6=75=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku4XzV:Taxv?012?0;75n2ceyQiqgomkc(agyS`{cdht,tuYhx;UyS=Qbuy2345:26::0ec}{_qksaioim&ceyQbumfjr*vwWfz9SQ?_lw{45674<4:>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}>2e9jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq0\vZ6Xff~;<=?>279jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq0\vZ7X8;<0ec}{_qksaioim&ceyQbumfjr*vwWfz9SQ>_005?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms6ZtX9V89:6gasu]smuckago$ec}{_lwo`lp(xyUd|?Q}_0]063=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku4XzV;T8?84ioqw[uowmecei"gasu]nqibn~&z{Sb~=_s]2[0413`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw:VxT=R8=f:kmwqYwayogeck ioqw[hskl`|$|}Q`p3]q[4Yj}q:;<=2?>228mkusWyc{iagae.kmwqYj}enbz"~_nr1[wY6Wds<=>?<1<26c=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku4XzV;Taxv?012?5;573`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw:VxT=Rczx12349799;l0ec}{_qksaioim&ceyQbumfjr*vwWfz9SQ>_lw{45674;48<6gasu]smuckago$ec}{_lwo`lp(xyUd|?Q}_0]nq}6789692<33?31b>oi{}U{e}kciog,mkusWdghdx pq]lt7YuW8Ufyu>?01>7:66R|P1^ov|56785?5=?h4ioqw[uowmecei"gasu]nqibn~&z{Sb~=_s]2[hs89:;0;0<0:kmwqYwayogeck ioqw[hskl`|$|}Q`p3]q[4Yj}q:;<=29>005?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms6ZtX:V:9:6gasu]smuckago$ec}{_lwo`lp(xyUd|?Q}_3]263=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku4XzV8T>?84ioqw[uowmecei"gasu]nqibn~&z{Sb~=_s]1[6413`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw:VxT>R:=6:kmwqYwayogeck ioqw[hskl`|$|}Q`p3]q[7Y2:?1bb~zPphrfhlhb'`dxxRczleku+uvXgy8T~R?<1<04>oi{}U{e}kciog,mkusWdghdx pq]lt7YuW;Ufyu>?01>3:44a3`dxxR~fpdnjj`)nfz~Taxbkiw-stZiw:VxT>Rczx1234979;91bb~zPphrfhlhb'`dxxRczleku+uvXgy8T~R>4ioqw[uowmecei"gasu]nqibn~&z{Sb~=_s]1[hs89:;0?0>2g9jjvrXx`zn`d`j/hlppZkrdmc}#}~Poq0\vZ4Xe|r;<=>33?13?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms6ZtX:Vg~t=>?0=1=57`R|P2^ov|56785?5?=5fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}228mkusWyc{iagae.kmwqYj}enbz"~_nr1[wY5Wds<=>?<7<263=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku4XzV9TR|P3^41b>oi{}U{e}kciog,mkusWdghdx pq]lt7YuW:Ufyu>?01>3:66R|P3^ov|56785;5=?h4ioqw[uowmecei"gasu]nqibn~&z{Sb~=_s]0[hs89:;0?0<0:kmwqYwayogeck ioqw[hskl`|$|}Q`p3]q[6Yj}q:;<=2=>00e?lht|Vzb|hbfnd-jjvrXe|foe{!p^ms6ZtX;Vg~t=>?0=1=75=nfz~T|d~jlhlf+lht|Vg~`igy/qr\ku4XzV9Taxv?012?7;75n2ceyQiqgomkc(agyS`{cdht,tuYhx;UyS>Qbuy2345:36::0ec}{_qksaioim&ceyQbumfjr*vwWfz9SQ<_lw{45674=4:>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzTc}?<7<04>oi{}U{e}kciog,mkusWdghdx pq]lt7YuW:Ufyu>?01>5:4433`dxxR~fpdnjj`)nfz~Taxbkiw-stZtbo5;;2?:4ioqw[uowmecei"gasu]nqibn~&z{Skh<03=61=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`a;9;4986gasu]smuckago$ec}{_lwo`lp(xyUyij2>3?07?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfc9736;>0ec}{_qksaioim&ceyQbumfjr*vwW{ol0<;1259jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde?5385<2ceyQiqgomkc(agyS`{cdht,tuYumn6:;3<;;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg=3;:7295fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hi321<10>oi{}U{e}kciog,mkusWdghdx pq]qab:5978?7d`|t^rjt`jnfl%bb~zPmtngms)wxVxnk1<=>368mkusWyc{iagae.kmwqYj}enbz"~_sgd8759:=1bb~zPphrfhlhb'`dxxRczleku+uvXzlm7>90=4:kmwqYwayogeck ioqw[hskl`|$|}Q}ef>11;433`dxxR~fpdnjj`)nfz~Taxbkiw-stZtbo58=2?:4ioqw[uowmecei"gasu]nqibn~&z{Skh<35=61=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`a;:14986gasu]smuckago$ec}{_lwo`lp(xyUyij2=9?07?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfc9576;>0ec}{_qksaioim&ceyQbumfjr*vwW{ol0>?1259jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde?7785<2ceyQiqgomkc(agyS`{cdht,tuYumn68?3<;;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg=17:7295fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hi337<10>oi{}U{e}kciog,mkusWdghdx pq]qab:4?78?7d`|t^rjt`jnfl%bb~zPmtngms)wxVxnk1=7>368mkusWyc{iagae.kmwqYj}enbz"~_sgd86?9:=1bb~zPphrfhlhb'`dxxRczleku+uvXzlm78=0=4:kmwqYwayogeck ioqw[hskl`|$|}Q}ef>75;433`dxxR~fpdnjj`)nfz~Taxbkiw-stZtbo5>92?:4ioqw[uowmecei"gasu]nqibn~&z{Skh<51=61=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`a;<=4986gasu]smuckago$ec}{_lwo`lp(xyUyij2;5?07?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfc9216;>0ec}{_qksaioim&ceyQbumfjr*vwW{ol0991259jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde?0=85<2ceyQiqgomkc(agyS`{cdht,tuYumn6?53<;;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg=73:7295fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hi353<10>oi{}U{e}kciog,mkusWdghdx pq]qab:2;78?7d`|t^rjt`jnfl%bb~zPmtngms)wxVxnk1;;>368mkusWyc{iagae.kmwqYj}enbz"~_sgd8039:=1bb~zPphrfhlhb'`dxxRczleku+uvXzlm79;0=4:kmwqYwayogeck ioqw[hskl`|$|}Q}ef>63;433`dxxR~fpdnjj`)nfz~Taxbkiw-stZtbo5?32?:4ioqw[uowmecei"gasu]nqibn~&z{Skh<4;=61=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`a;>94986gasu]smuckago$ec}{_lwo`lp(xyUyij291?07?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfc9056;>0ec}{_qksaioim&ceyQbumfjr*vwW{ol0;=1229jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde?<;443`dxxR~fpdnjj`)nfz~Taxbkiw-stZtbo535>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiP1100?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZ76::1bb~zPphrfhlhb'`dxxRczleku+uvXzlmT=?<<;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg^3066=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aX9=887d`|t^rjt`jnfl%bb~zPmtngms)wxVxnkR?:229jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde\53443`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboV;<>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiP1900?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZ7>::1bb~zPphrfhlhb'`dxxRczleku+uvXzlmT>=<<;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg^0266=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aX:;887d`|t^rjt`jnfl%bb~zPmtngms)wxVxnkR<<229jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde\61443`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboV8>>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiP2700?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZ40::1bb~zPphrfhlhb'`dxxRczleku+uvXzlmT>5<<;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg^0:66=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aX;9887d`|t^rjt`jnfl%bb~zPmtngms)wxVxnkR=>229jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde\77443`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboV98>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiP3500?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZ52::1bb~zPphrfhlhb'`dxxRczleku+uvXzlmT?;<<;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg^1466=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aX;1887d`|t^rjt`jnfl%bb~zPmtngms)wxVxnkR=6229jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde\05443`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboV>:>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiP4300?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZ24::1bb~zPphrfhlhb'`dxxRczleku+uvXzlmT89<<;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg^6666=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aX2>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiP5100?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZ36::1bb~zPphrfhlhb'`dxxRczleku+uvXzlmT9?<<;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg^7066=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aX==887d`|t^rjt`jnfl%bb~zPmtngms)wxVxnkR;:229jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde\13443`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboV?<>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiP5900?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZ3>::1bb~zPphrfhlhb'`dxxRczleku+uvXzlmT:=<<;hlppZvnxlfbbh!fnrv\ipjca%{|R|jg^4266=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aX>;887d`|t^rjt`jnfl%bb~zPmtngms)wxVxnkR8<239jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde\<74?01>24;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboVg~t=>?0=33:44d3`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboVg~t=>?0=32:7b?<03=57e?<00=6a=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aXe|r;<=>313<26f=nfz~T|d~jlhlf+lht|Vg~`igy/qr\v`aXe|r;<=>312<1`>oi{}U{e}kciog,mkusWdghdx pq]qabYj}q:;<=2>3?31g>oi{}U{e}kciog,mkusWdghdx pq]qabYj}q:;<=2>4?0g?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZkrp9:;<1?;>00`?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZkrp9:;<1?:>3f8mkusWyc{iagae.kmwqYj}enbz"~_sgd[hs89:;0<;113`8mkusWyc{iagae.kmwqYj}enbz"~_sgd[hs89:;0<0=c:kmwqYwayogeck ioqw[hskl`|$|}Q}ef]nq}67896:2<n5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiPmtz3456;:7;9n6gasu]smuckago$ec}{_lwo`lp(xyUyijQbuy2345:46;i0ec}{_qksaioim&ceyQbumfjr*vwW{olS`{w01238686:k1bb~zPphrfhlhb'`dxxRczleku+uvXzlmTaxv?012?0;4d3`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboVg~t=>?0=6=57d?<4<1g>oi{}U{e}kciog,mkusWdghdx pq]qabYj}q:;<=2:>00a?lht|Vzb|hbfnd-jjvrXe|foe{!p^pfcZkrp9:;<1812b9jjvrXx`zn`d`j/hlppZkrdmc}#}~Prde\ip~789:7:3?=b:kmwqYwayogeck ioqw[hskl`|$|}Q}ef]nq}67896<2?m4ioqw[uowmecei"gasu]nqibn~&z{Skh_lw{45674>4:>o5fnrv\tlvbd`dn#d`|t^ovhaoq'yzT~hiPmtz3456;078h7d`|t^rjt`jnfl%bb~zPmtngms)wxVxnkRczx12349>99;h0ec}{_qksaioim&ceyQbumfjr*vwW{olS`{w01238<85k2ceyQiqgomkc(agyS`{cdht,tuYumnUfyu>?01>::44?3`dxxR~fpdnjj`)nfz~Taxbkiw-stZtboVddx=>?13;8mkusWyc{iagae.kmwqYj}enbz"~_sgd[kis89::=?84ioqw[uowmecei"gasu]nqibn~&z{mijPcxk?4;413`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWjsb0<0=6:kmwqYwayogeck ioqw[hskl`|$|}okd^azm949:?1bb~zPphrfhlhb'`dxxRczleku+uvflmUhud2<>3g8mkusWyc{iagae.kmwqYj}enbz"~aef\g|oX8Vg~t=>?200e?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[fnW9Ufyu>?03326c=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYdq`U;S`{w0121644b3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWjsbS3:Zkffm8m7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><1k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>3:9776Vgjbi=?;hlppZvnxlfbbh!fnrv\ipjca%{|ljk_nr2858;994Tal`k13d8mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;876:=3Qbaof04>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95:50=31:Zkffm;9j6gasu]smuckago$ec}{_lwo`lp(xykohRa1=2=8459Wdkeh>>4ioqw[uowmecei"gasu]nqibn~&z{mijPoq3?4;:6;7Ufmcj>2g9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:765;?2Rcnne13?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv64947=90Pm`lg57`5?]nekb482ceyQiqgomkc(agyS`{cdht,tugclVe{=1>1<07=[hgil88m7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><13:9716Vgjbi?=f:kmwqYwayogeck ioqw[hskl`|$|}okd^ms596948=5S`oad228mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;876:;3Qbaof26c=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86;21?7>^obja573`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0=0319<\idhc9;l0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?30?>2=;Yjign8<6gasu]smuckago$ec}{_lwo`lp(xykohRa1=2=84?9Wdkeh<oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95:50?>1_lcm`44a3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0=0320<\idhc;91bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2?>=02:Zkffm;9j6gasu]smuckago$ec}{_lwo`lp(xykohRa1=2=8749Wdkeh>>4ioqw[uowmecei"gasu]nqibn~&z{mijPoq3?4;:5:7Ufmcj>2g9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:765882Rcnne13?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv64947>>0Pm`lg57`1<36=[hgil88m7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><13:9426Vgjbi?=f:kmwqYwayogeck ioqw[hskl`|$|}okd^ms59694;<5S`oad228mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;8769:3Qbaof26c=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86;21<8>^obja573`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0=0326<\idhc9;l0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?30?>1<;Yjign8<6gasu]smuckago$ec}{_lwo`lp(xykohRa1=2=87>9Wdkeh<oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95:50?0Pm`lg6c=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86;21<1_lcm`44a3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0=0331<\idhc;91bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2?>=13:Zkffm;9j6gasu]smuckago$ec}{_lwo`lp(xykohRa1=2=8679Wdkeh>>4ioqw[uowmecei"gasu]nqibn~&z{mijPoq3?4;:497Ufmcj>2d9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:76595S`oad3d8mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;87682Rcnne31a>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95:5090Pm`lg6c=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86;21:1_lcm`44b3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0=035?]nekb5n2ceyQiqgomkc(agyS`{cdht,tugclVe{=1>1<4<\idhc9;o0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?30?>5:Zkffm8m7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><1h5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>3:919Wdkeh?h4ioqw[uowmecei"gasu]nqibn~&z{mijPoq3?4;:06Vgjbi?=e:kmwqYwayogeck ioqw[hskl`|$|}okd^ms5969414Tal`k2g9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:76525S`oad00f?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv6494753Qbaof1b>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95:5040Pm`lg57c^obja4a3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0<030?]nekb6:o1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2>>=33:Zkffm9;7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><0^obja75n2ceyQiqgomkc(agyS`{cdht,tugclVe{=1?1<01=[hgil::0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?31?>27;Yjign:>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>2:9736Vgjbi=?;hlppZvnxlfbbh!fnrv\ipjca%{|ljk_nr2848;9=4Tal`k13d8mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;976:93Qbaof04>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95;50<;1_lcm`44a3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0<0317<\idhc;91bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2>>=35:Zkffm;9j6gasu]smuckago$ec}{_lwo`lp(xykohRa1=3=8419Wdkeh>>4ioqw[uowmecei"gasu]nqibn~&z{mijPoq3?5;:6?7Ufmcj>2g9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:665;32Rcnne13?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv64847=50Pm`lg57`9?]nekb482ceyQiqgomkc(agyS`{cdht,tugclVe{=1?1<0;=[hgil88n7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><0<0Pm`lg75=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86:21<>>^obja75n2ceyQiqgomkc(agyS`{cdht,tugclVe{=1?1<30=[hgil::0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?31?>16;Yjign:>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>2:9446Vgjbi=?;hlppZvnxlfbbh!fnrv\ipjca%{|ljk_nr2848;::4Tal`k13d8mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;976983Qbaof04>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95;50?:1_lcm`44a3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0<0324<\idhc;91bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2>>=06:Zkffm;9j6gasu]smuckago$ec}{_lwo`lp(xykohRa1=3=8709Wdkeh>>4ioqw[uowmecei"gasu]nqibn~&z{mijPoq3?5;:5>7Ufmcj>2g9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:6658<2Rcnne13?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv64847>:0Pm`lg57`<02:94>6Vgjbi?=e:kmwqYwayogeck ioqw[hskl`|$|}okd^ms59794;4Tal`k2g9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:66585S`oad00e?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv64847?=0Pm`lg75=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86:21=?>^obja75n2ceyQiqgomkc(agyS`{cdht,tugclVe{=1?1<23=[hgil::0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?31?>05;Yjign:>h5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>2:959Wdkeh?h4ioqw[uowmecei"gasu]nqibn~&z{mijPoq3?5;:46Vgjbi?=e:kmwqYwayogeck ioqw[hskl`|$|}okd^ms59794=4Tal`k2g9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:665>5S`oad00f?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv6484793Qbaof1b>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95;5080Pm`lg57c^obja4a3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0<036?]nekb6:l1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2>>=5=[hgil;l0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?31?>4:Zkffm;9i6gasu]smuckago$ec}{_lwo`lp(xykohRa1=3=8=8Xehdo>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>2:9>9Wdkeh<^obja573`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0?0311<\idhc9;l0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?32?>25;Yjign8<6gasu]smuckago$ec}{_lwo`lp(xykohRa1=0=8479Wdkeh<oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95850<=1_lcm`6632>3?]nekb6:o1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2=>=37:Zkffm9;7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><3^obja75n2ceyQiqgomkc(agyS`{cdht,tugclVe{=1<1<05=[hgil::0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?32?>23;Yjign:>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>1:97?6Vgjbi=?;hlppZvnxlfbbh!fnrv\ipjca%{|ljk_nr2878;914Tal`k13d8mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;:76:53Qbaof04>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95850<71_lcm`44b3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0?031?]nekb5n2ceyQiqgomkc(agyS`{cdht,tugclVe{=1<1<0<\idhc9;l0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?32?>14;Yjign8<6gasu]smuckago$ec}{_lwo`lp(xykohRa1=0=8769Wdkeh<oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95850?<1_lcm`6632=2?]nekb6:o1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2=>=00:Zkffm9;7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><35S`oad00e?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv64;47>80Pm`lg75=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86921<:>^obja75n2ceyQiqgomkc(agyS`{cdht,tugclVe{=1<1<34=[hgil::0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?32?>12;Yjign:>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>1:9406Vgjbi=?;hlppZvnxlfbbh!fnrv\ipjca%{|ljk_nr2878;:>4Tal`k13d8mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;:76943Qbaof04>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95850?61_lcm`44a3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0?0328<\idhc;91bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2=>=0::Zkffm;9i6gasu]smuckago$ec}{_lwo`lp(xykohRa1=0=878Xehdo>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>1:949Wdkeh<oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95850>?1_lcm`6632<1?]nekb6:l1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2=>=1=[hgil;l0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?32?>0:Zkffm;9i6gasu]smuckago$ec}{_lwo`lp(xykohRa1=0=818Xehdo>k5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0>1:929Wdkeh<328>^obja75m2ceyQiqgomkc(agyS`{cdht,tugclVe{=1<1<9<\idhc:o1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2=>=:=[hgil88n7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><32g9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:465;;2Rcnne13?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[jv64:47==0Pm`lg57`1?]nekb482ceyQiqgomkc(agyS`{cdht,tugclVe{=1=1<03=[hgil88m7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><20:9756Vgjbi?=f:kmwqYwayogeck ioqw[hskl`|$|}okd^ms59594895S`oad228mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;;76:?3Qbaof26c=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86821?;>^obja573`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0>0315<\idhc9;l0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?33?>21;Yjign8<6gasu]smuckago$ec}{_lwo`lp(xykohRa1=1=8439Wdkeh<oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95950<91_lcm`667?]nekb6:o1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2<>=3;:Zkffm9;7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><2oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95950<0Pm`lg57`<20:9466Vgjbi?=f:kmwqYwayogeck ioqw[hskl`|$|}okd^ms59594;85S`oad228mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;;769>3Qbaof26c=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86821<<>^obja573`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0>0322<\idhc9;l0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?33?>10;Yjign8<6gasu]smuckago$ec}{_lwo`lp(xykohRa1=1=8729Wdkeh<2Rcnne31b>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw95950?81_lcm`66=04:Zkffm9;7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><240Pm`lg75=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86821<6>^obja75m2ceyQiqgomkc(agyS`{cdht,tugclVe{=1=1<3<\idhc:o1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2<>=0=[hgil88m7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><20:9576Vgjbi?=f:kmwqYwayogeck ioqw[hskl`|$|}okd^ms59594:;5S`oad228mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;;768=3Qbaof26`=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx86821=1_lcm`7`^obja75m2ceyQiqgomkc(agyS`{cdht,tugclVe{=1=1<5<\idhc:o1bb~zPphrfhlhb'`dxxRczleku+uvflmUd|<2<>=6=[hgil88n7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~><27Ufmcj>2d9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]lt4:465=5S`oad3d8mkusWyc{iagae.kmwqYj}enbz"~aef\ku7;;76<2Rcnne31a>oi{}U{e}kciog,mkusWdghdx pqcg`Ziw9595050Pm`lg6c=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYhx8682161_lcm`44b3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcWfz:0>039?]nekb5n2ceyQiqgomkc(agyS`{cdht,tugclVe{=1=1<8<\idhc9;n0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?P0^ov|567:;o0ec}{_qksaioim&ceyQbumfjr*vwimnTc}?P0^ov|567:88o7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~>_0]nq}678;8n7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSb~>_0]nq}678;;9h6gasu]smuckago$ec}{_lwo`lp(xykohRa1^0\ip~78989i6gasu]smuckago$ec}{_lwo`lp(xykohRa1^0\ip~7898:>i5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0]0[hs89:9>h5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ`p0]0[hs89:9=?74ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?4;:76;k0ec}{_qksaioim&ceyQbumfjr*vwimnT~h}30?>24;4f3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcW{ox0=0310<1e>oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{5:50<<12`9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]qav:765;82?o4ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?4;:6<78j7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSk|<11<04=6d=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYumz6;21?8>3c8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;876:431<32=6d=nfz~T|d~jlhlf+lht|Vg~`igy/qrb`aYumz6;21<>>3c8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;8769>3=06:7g:0=a:kmwqYwayogeck ioqw[hskl`|$|}okd^pfw9694;25>l5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ}er>3:94>6;30ec}{_qksaioim&ceyQbumfjr*vwimnT~h}30?>1:7g1<4<1=>oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{5:50;0=9:kmwqYwayogeck ioqw[hskl`|$|}okd^pfw9694>4956gasu]smuckago$ec}{_lwo`lp(xykohR|js=2=8=8512ceyQiqgomkc(agyS`{cdht,tugclVxn1>1<8<1=>oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{5;50=0=a:kmwqYwayogeck ioqw[hskl`|$|}okd^pfw97948:5>l5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ}er>2:9766;k0ec}{_qksaioim&ceyQbumfjr*vwimnT~h}31?>26;4f3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcW{ox0<0312<1e>oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{5;50<:12`9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]qav:665;>2?o4ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?5;:6>78j7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSk|<03;8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;976:2?o4ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?5;:5878j7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSk|<03c8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;976983>=04:7g40=9:kmwqYwayogeck ioqw[hskl`|$|}okd^pfw9794;49m6gasu]smuckago$ec}{_lwo`lp(xykohR|js=3=8669:h1bb~zPphrfhlhb'`dxxRczleku+uvflmUyi~2>>=12:7?3;8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;976?2?74ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?5;:26;30ec}{_qksaioim&ceyQbumfjr*vwimnT~h}31?>5:7?3;8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;97632?74ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?5;:>6;30ec}{_qksaioim&ceyQbumfjr*vwimnT~h}32?>3:7g32>0?0b?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[wct4;47=<0=a:kmwqYwayogeck ioqw[hskl`|$|}okd^pfw9494885>l5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ}er>1:9746;k0ec}{_qksaioim&ceyQbumfjr*vwimnT~h}32?>20;4f3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcW{ox0?0314<1e>oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{5850<812`9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]qav:565;<2?o4ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?6;:6078j7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSk|<3oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{5850?>12`9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]qav:5658:2?o4ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?6;:5:78j7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSk|<33c8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;:769:349m6gasu]smuckago$ec}{_lwo`lp(xykohR|js=0=87>9:h1bb~zPphrfhlhb'`dxxRczleku+uvflmUyi~2=>=0::7?32=>3c8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;:768<3oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{585080=9:kmwqYwayogeck ioqw[hskl`|$|}okd^pfw9494?4956gasu]smuckago$ec}{_lwo`lp(xykohR|js=0=828512ceyQiqgomkc(agyS`{cdht,tugclVxn1<1<9<1=>oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{585040=9:kmwqYwayogeck ioqw[hskl`|$|}okd^pfw9594949m6gasu]smuckago$ec}{_lwo`lp(xykohR|js=1=8469:h1bb~zPphrfhlhb'`dxxRczleku+uvflmUyi~2<>=32:7g2?0b?lht|Vzb|hbfnd-jjvrXe|foe{!p`fg[wct4:47=>0=a:kmwqYwayogeck ioqw[hskl`|$|}okd^pfw95948>5>l5fnrv\tlvbd`dn#d`|t^ovhaoq'yzjhiQ}er>0:9726;k0ec}{_qksaioim&ceyQbumfjr*vwimnT~h}33?>22;4f3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcW{ox0>0316<1e>oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{5950<612`9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]qav:465;22?74ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?7;:66;k0ec}{_qksaioim&ceyQbumfjr*vwimnT~h}33?>14;4f3`dxxR~fpdnjj`)nfz~Taxbkiw-stdbcW{ox0>0320<1e>oi{}U{e}kciog,mkusWdghdx pqcg`Ztb{5950?<12`9jjvrXx`zn`d`j/hlppZkrdmc}#}~nde]qav:465882?o4ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?7;:5<78j7d`|t^rjt`jnfl%bb~zPmtngms)wxhnoSk|<23c8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;;76943>3;8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;;7682?74ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?7;:36;30ec}{_qksaioim&ceyQbumfjr*vwimnT~h}33?>6:7?3;8mkusWyc{iagae.kmwqYj}enbz"~aef\v`u;;76<2?74ioqw[uowmecei"gasu]nqibn~&z{mijPrdq?7;:?6;30ec}{_qksaioim&ceyQbumfjr*vwimnT~h}33?>::75P1368mkusWyc{iagae.kmwqYj}enbz"~rnf\4Z77:=1bb~zPphrfhlhb'`dxxRczleku+uvugmU;SP1707?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Y6?;>0ec}{_qksaioim&ceyQbumfjr*vwzfnT?:4ioqw[uowmecei"gasu]nqibn~&z{~bjP0^0361=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY7W;;986gasu]smuckago$ec}{_lwo`lp(xyxdhR>P2307?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Y5;;>0ec}{_qksaioim&ceyQbumfjr*vwzfnT;<;;hlppZvnxlfbbh!fnrv\ipjca%{|ak_1]137295fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ?_3;17>oi{}U{e}kciog,mkusWdghdx pqpl`Z6X;;>0ec}{_qksaioim&ceyQbumfjr*vwzfnT95fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ?_2710>oi{}U{e}kciog,mkusWdghdx pqpl`Z6X;?8?7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS=Q<7368mkusWyc{iagae.kmwqYj}enbz"~rnf\4Z5?:=1bb~zPphrfhlhb'`dxxRczleku+uvugmU;S>7=3:kmwqYwayogeck ioqw[hskl`|$|}|`d^2\075P6318mkusWyc{iagae.kmwqYj}enbz"~rnf\4Z15;2ceyQiqgomkc(agyS`{cdht,tuthlV:T4?=4ioqw[uowmecei"gasu]nqibn~&z{~bjP0^;1g>oi{}U{e}kciog,mkusWdghdx pqpl`Z6Xe|r;<=>30?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>0?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>1?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>2?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>3?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>4?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>5?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>6?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>7?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>8?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>9?0`?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[5Yj}q:;<=2>>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<13f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<>>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<=>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<<>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<;>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<:>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<9>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<8>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<7>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<6>3a8mkusWyc{iagae.kmwqYj}enbz"~rnf\4Zkrp9:;<1<12e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>>12e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>?12e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0><12e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>=12e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>:12e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>;12e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>812e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>912e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>612e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>712b9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]3[hs89:;0>0=c:kmwqYwayogeck ioqw[hskl`|$|}|`d^2\ip~789:7832?m4ioqw[uowmecei"gasu]nqibn~&z{~bjP0^ov|56785<5>n5fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ?_lw{45674>49o6gasu]smuckago$ec}{_lwo`lp(xyxdhR>Pmtz3456;078h7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS=Qbuy2345:>6;30ec}{_qksaioim&ceyQbumfjr*vwzfnT?1000?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[4Y7::1bb~zPphrfhlhb'`dxxRczleku+uvugmU:S<<;;hlppZvnxlfbbh!fnrv\ipjca%{|ak_0]247295fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ>_0010>oi{}U{e}kciog,mkusWdghdx pqpl`Z7X9:8?7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS4368mkusWyc{iagae.kmwqYj}enbz"~rnf\5Z72:=1bb~zPphrfhlhb'`dxxRczleku+uvugmU:S<8=4:kmwqYwayogeck ioqw[hskl`|$|}|`d^3\52433`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW8U:4?:4ioqw[uowmecei"gasu]nqibn~&z{~bjP1^3:66=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY6W;8?7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS0ec}{_qksaioim&ceyQbumfjr*vwzfnT=R<6229jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]2[6433`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW8U80ec}{_qksaioim&ceyQbumfjr*vwzfnT=R=:259jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]2[605<2ceyQiqgomkc(agyS`{cdht,tuthlV;T?:<;;hlppZvnxlfbbh!fnrv\ipjca%{|ak_0]0<72>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ>_500?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[4Y2::1bb~zPphrfhlhb'`dxxRczleku+uvugmU:S;<<;hlppZvnxlfbbh!fnrv\ipjca%{|ak_0]466=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY6W1887d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS0=d:kmwqYwayogeck ioqw[hskl`|$|}|`d^3\ip~789:7=90=d:kmwqYwayogeck ioqw[hskl`|$|}|`d^3\ip~789:7=80=d:kmwqYwayogeck ioqw[hskl`|$|}|`d^3\ip~789:7=;0=d:kmwqYwayogeck ioqw[hskl`|$|}|`d^3\ip~789:7=:0=d:kmwqYwayogeck ioqw[hskl`|$|}|`d^3\ip~789:7=50=d:kmwqYwayogeck ioqw[hskl`|$|}|`d^3\ip~789:7=40=c:kmwqYwayogeck ioqw[hskl`|$|}|`d^3\ip~789:7=332?j4ioqw[uowmecei"gasu]nqibn~&z{~bjP1^ov|567859=2?j4ioqw[uowmecei"gasu]nqibn~&z{~bjP1^ov|567859<2?j4ioqw[uowmecei"gasu]nqibn~&z{~bjP1^ov|56785932?j4ioqw[uowmecei"gasu]nqibn~&z{~bjP1^ov|56785922?m4ioqw[uowmecei"gasu]nqibn~&z{~bjP1^ov|5678595>n5fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ>_lw{45674=49o6gasu]smuckago$ec}{_lwo`lp(xyxdhR?Pmtz3456;=78h7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ=_007?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Y68;>0ec}{_qksaioim&ceyQbumfjr*vwzfnT>R?>259jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]1[445<2ceyQiqgomkc(agyS`{cdht,tuthlV8T=><;;hlppZvnxlfbbh!fnrv\ipjca%{|ak_3]2072>95fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ=_0410>oi{}U{e}kciog,mkusWdghdx pqpl`Z4X9>8?7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS?Q>8368mkusWyc{iagae.kmwqYj}enbz"~rnf\6Z7>::1bb~zPphrfhlhb'`dxxRczleku+uvugmU9S?<;;hlppZvnxlfbbh!fnrv\ipjca%{|ak_3]147295fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ=_3010>oi{}U{e}kciog,mkusWdghdx pqpl`Z4X::8?7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS?Q=4368mkusWyc{iagae.kmwqYj}enbz"~rnf\6Z42:=1bb~zPphrfhlhb'`dxxRczleku+uvugmU9S?8=4:kmwqYwayogeck ioqw[hskl`|$|}|`d^0\62433`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW;U94?:4ioqw[uowmecei"gasu]nqibn~&z{~bjP2^0:66=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY5W:8?7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS?Q<0368mkusWyc{iagae.kmwqYj}enbz"~rnf\6Z56:=1bb~zPphrfhlhb'`dxxRczleku+uvugmU9S><=4:kmwqYwayogeck ioqw[hskl`|$|}|`d^0\76433`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW;U88?:4ioqw[uowmecei"gasu]nqibn~&z{~bjP2^1661=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY5W:<986gasu]smuckago$ec}{_lwo`lp(xyxdhR0ec}{_qksaioim&ceyQbumfjr*vwzfnT>R=6229jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]1[1443`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW;U>>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ=_700?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Y0::1bb~zPphrfhlhb'`dxxRczleku+uvugmU9S5<<;hlppZvnxlfbbh!fnrv\ipjca%{|ak_3]:6f=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY5Wds<=>?<1<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>311<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>310<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>313<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>312<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>315<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>314<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>317<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>316<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>319<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>318<1g>oi{}U{e}kciog,mkusWdghdx pqpl`Z4Xe|r;<=>31?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=0?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=1?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=2?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=3?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=4?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=5?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=6?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=7?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=8?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=9?0`?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[7Yj}q:;<=2=>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=?>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=>>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1==>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=<>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=;>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=:>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=9>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=8>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=7>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=6>3a8mkusWyc{iagae.kmwqYj}enbz"~rnf\6Zkrp9:;<1=12b9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]1[hs89:;090=c:kmwqYwayogeck ioqw[hskl`|$|}|`d^0\ip~789:793n5fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ=_lw{45674149o6gasu]smuckago$ec}{_lwo`lp(xyxdhRQ?229jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]0[4433`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW:U:0ec}{_qksaioim&ceyQbumfjr*vwzfnT?R?:259jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]0[405<2ceyQiqgomkc(agyS`{cdht,tuthlV9T=:<;;hlppZvnxlfbbh!fnrv\ipjca%{|ak_2]2<72>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ<_307?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[6Y58;>0ec}{_qksaioim&ceyQbumfjr*vwzfnT?R<>259jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]0[745<2ceyQiqgomkc(agyS`{cdht,tuthlV9T>><;;hlppZvnxlfbbh!fnrv\ipjca%{|ak_2]1072>95fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ<_3410>oi{}U{e}kciog,mkusWdghdx pqpl`Z5X:>8?7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS>Q=8368mkusWyc{iagae.kmwqYj}enbz"~rnf\7Z4>::1bb~zPphrfhlhb'`dxxRczleku+uvugmU8S><;;hlppZvnxlfbbh!fnrv\ipjca%{|ak_2]047295fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ<_2010>oi{}U{e}kciog,mkusWdghdx pqpl`Z5X;:8?7d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS>Q<4368mkusWyc{iagae.kmwqYj}enbz"~rnf\7Z52:=1bb~zPphrfhlhb'`dxxRczleku+uvugmU8S>8=4:kmwqYwayogeck ioqw[hskl`|$|}|`d^1\72433`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW:U84?:4ioqw[uowmecei"gasu]nqibn~&z{~bjP3^1:66=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY4W=887d`|t^rjt`jnfl%bb~zPmtngms)wx{eoS>Q:229jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]0[3443`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW:U<>>5fnrv\tlvbd`dn#d`|t^ovhaoq'yzyciQ<_900?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[6Y>:j1bb~zPphrfhlhb'`dxxRczleku+uvugmU8S`{w01238585l2ceyQiqgomkc(agyS`{cdht,tuthlV9Taxv?012?4;75k2ceyQiqgomkc(agyS`{cdht,tuthlV9Taxv?012?5;4c3`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW:Ufyu>?01>2:44d3`dxxR~fpdnjj`)nfz~Taxbkiw-stwicW:Ufyu>?01>1:7b?0=0=57e?0=1=6a=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY4Wds<=>?<2<26f=nfz~T|d~jlhlf+lht|Vg~`igy/qrqkaY4Wds<=>?<5<1`>oi{}U{e}kciog,mkusWdghdx pqpl`Z5Xe|r;<=>34?31g>oi{}U{e}kciog,mkusWdghdx pqpl`Z5Xe|r;<=>35?0g?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[6Yj}q:;<=2:>00`?lht|Vzb|hbfnd-jjvrXe|foe{!psmg[6Yj}q:;<=29>3f8mkusWyc{iagae.kmwqYj}enbz"~rnf\7Zkrp9:;<18113a8mkusWyc{iagae.kmwqYj}enbz"~rnf\7Zkrp9:;<1912e9jjvrXx`zn`d`j/hlppZkrdmc}#}~}oe]0[hs89:;0:0>269jjvrXx`zn`d`j/hlppZkrdmc}#}|j_bmmwqY7W98<7d`|t^rjt`jnfl%bb~zPmtngms)wzlUhcc}{_1]26==nfz~T|d~jlhlf+lht|Vg~`igy/qpf[fii{}U;S<>=8:kmwqYwayogeck ioqw[hskl`|$|kPcnlppZ6X98837d`|t^rjt`jnfl%bb~zPmtngms)wzlUhcc}{_1]267>946gasu]smuckago$ec}{_lwo`lp(x{oTob`|t^2\504?3`dxxR~fpdnjj`)nfz~Taxbkiw-sv`YdggyS=Q>63:8mkusWyc{iagae.kmwqYj}enbz"~}e^aljvrX8V;<>55fnrv\tlvbd`dn#d`|t^ovhaoq'yxnSnaasu]3[4>502ceyQiqgomkc(agyS`{cdht,twcXkfdxxR>P1804?lht|Vzb|hbfnd-jjvrXe|foe{!rd]`kkusW9U9>55fnrv\tlvbd`dn#d`|t^ovhaoq'yxnSnaasu]3[76502ceyQiqgomkc(agyS`{cdht,twcXkfdxxR>P200;?lht|Vzb|hbfnd-jjvrXe|foe{!rd]`kkusW9U9>?64ioqw[uowmecei"gasu]nqibn~&zyiRm`nrv\4Z44:11bb~zPphrfhlhb'`dxxRczleku+utbWjeeyQ?_361<>oi{}U{e}kciog,mkusWdghdx psg\gjht|V:T>8<7;hlppZvnxlfbbh!fnrv\ipjca%{~hQlooqw[5Y5>;20ec}{_qksaioim&ceyQbumfjr*vumVidb~zP0^046==nfz~T|d~jlhlf+lht|Vg~`igy/qpf[fii{}U;S?6=8:kmwqYwayogeck ioqw[hskl`|$|kPcnlppZ6X:08<7d`|t^rjt`jnfl%bb~zPmtngms)wzlUhcc}{_1]06==nfz~T|d~jlhlf+lht|Vg~`igy/qpf[fii{}U;S>>=8:kmwqYwayogeck ioqw[hskl`|$|kPcnlppZ6X;88<7d`|t^rjt`jnfl%bb~zPmtngms)wzlUhcc}{_1]762=nfz~T|d~jlhlf+lht|Vg~`igy/qpf[fii{}U;S8<8;hlppZvnxlfbbh!fnrv\ipjca%{~hQlooqw[5Y1:>1bb~zPphrfhlhb'`dxxRczleku+utbWjeeyQ?_604?lht|Vzb|hbfnd-jjvrXe|foe{!rd]`kkusW9U3>:5fnrv\tlvbd`dn#d`|t^ovhaoq'yxnSnaasu]3[<573`dxxR~fpdnjj`)nfz~Taxbkiw-sv`YdggyS=Qbuy2344:76:80ec}{_qksaioim&ceyQbumfjr*vumVidb~zP0^ov|56795:5=<==;hlppZvnxlfbbh!fnrv\ipjca%{~hQlooqw[5Yj}q:;<<2?>3300>oi{}U{e}kciog,mkusWdghdx psg\gjht|V:Taxv?013?4;YT_89:7d`|t^rjt`jnfl%bb~zPmtngms)wzlUhcc}{_1]nq}67886:<3==;hlppZvnxlfbbh!fnrv\ipjca%{~hQlooqw[5Yj}q:;<<2>0?305>oi{}U{e}kciog,mkusWdghdx psg\gjht|V:Taxv?013?5484:2ceyQiqgomkc(agyS`{cdht,twcXkfdxxR>Pmtz3457;984:?<5fnrv\tlvbd`dn#d`|t^ovhaoq'yxnSnaasu]3[hs89::0<<1339jjvrXx`zn`d`j/hlppZkrdmc}#}|j_bmmwqY7Wds<=>><00=567;hlppZvnxlfbbh!fnrv\ipjca%{~hQlooqw[5Yj}q:;<<2>4?11?lht|Vzb|hbfnd-jjvrXe|foe{!rd]`kkusW9Ufyu>?00>20;7492ceyQiqgomkc(agyS`{cdht,twcXkfdxxR>Pmtz3457;9<48>6gasu]smuckago$ec}{_lwo`lp(x{oTob`|t^2\ip~789;7=80>309jjvrXx`zn`d`j/hlppZkrdmc}#}|j_bmmwqY7Wds<=>><04=77=nfz~T|d~jlhlf+lht|Vg~`igy/qpf[fii{}U;S`{w012284099:;0ec}{_qksaioim&ceyQbumfjr*vumVidb~zP0^ov|56795;<2><4ioqw[uowmecei"gasu]nqibn~&zyiRm`nrv\4Zkrp9:;=1?8>012?lht|Vzb|hbfnd-jjvrXe|foe{!rd]`kkusW9Ufyu>?00>2<;553`dxxR~fpdnjj`)nfz~Taxbkiw-sv`YdggyS=Qbuy2344:607;8=6gasu]smuckago$ec}{_lwo`lp(x{oTob`|t^2\ip~789;7=40<2:kmwqYwayogeck ioqw[hskl`|$|kPcnlppZ6Xe|r;<=?318<275=nfz~T|d~jlhlf+lht|Vg~`igy/qpf[fii{}U;S`{w0122848492ceyQiqgomkc(agyS`{cdht,twcXkfdxxR>Pmtz3457;97;8=6gasu]smuckago$ec}{_lwo`lp(x{oTob`|t^2\ip~789;7>=0<2:kmwqYwayogeck ioqw[hskl`|$|kPcnlppZ6Xe|r;<=?321<274=nfz~T|d~jlhlf+lht|Vg~`igy/qpf[fii{}U;S`{w01228779;;1bb~zPphrfhlhb'`dxxRczleku+utbWjeeyQ?_lw{45664;;5=>?4ioqw[uowmecei"gasu]nqibn~&zyiRm`nrv\4Zkrp9:;=1<=>208mkusWyc{iagae.kmwqYj}enbz"~}e^aljvrX8Vg~t=>?1=01:4563`dxxR~fpdnjj`)nfz~Taxbkiw-sv`YdggyS=Qbuy2344:5;7997d`|t^rjt`jnfl%bb~zPmtngms)wzlUhcc}{_1]nq}678869?3?<1:kmwqYwayogeck ioqw[hskl`|$|kPcnlppZ6Xe|r;<=?325<06>oi{}U{e}kciog,mkusWdghdx psg\gjht|V:Taxv?013?6186;81bb~zPphrfhlhb'`dxxRczleku+utbWjeeyQ?_lw{45664;?5??5fnrv\tlvbd`dn#d`|t^ovhaoq'yxnSnaasu]3[hs89::0?;11238mkusWyc{iagae.kmwqYj}enbz"~}e^aljvrX8Vg~t=>?1=05:64oi{}U{e}kciog,mkusWdghdx psg\gjht|V:Taxv?013?6=84:2ceyQiqgomkc(agyS`{cdht,twcXkfdxxR>Pmtz3457;:14:?<5fnrv\tlvbd`dn#d`|t^ovhaoq'yxnSnaasu]3[hs89::0?71339jjvrXx`zn`d`j/hlppZkrdmc}#}|j_bmmwqY7Wds<=>><3;=566>1339jjvrXx`zn`d`j/hlppZkrdmc}#}|j_bmmwqY7Wds<=>><22=567238mkusWyc{iagae.kmwqYj}enbz"~}e^aljvrX8Vg~t=>?1=1=566oi{}U{e}kciog,mkusWdghdx psg\gjht|V:Taxv?013?2;563`dxxR~fpdnjj`)nfz~Taxbkiw-sv`YdggyS=Qbuy2344:1689;7d`|t^rjt`jnfl%bb~zPmtngms)wzlUhcc}{_1]nq}67886<2>?4ioqw[uowmecei"gasu]nqibn~&zyiRm`nrv\4Zkrp9:;=1911228mkusWyc{iagae.kmwqYj}enbz"~}e^aljvrX8Vg~t=>?1=:=74=nfz~T|d~jlhlf+lht|Vg~`igy/qpf[fii{}U;S`{w01228=86;91bb~zPphrfhlhb'`dxxRczleku+utbWjeeyQ?_lw{45664048=6gasu]smuckago$ec}{_lwo`lp(x{oTob`|t^2\ip~789;753?=d:kmwqYwayogeck ioqw[hskl`|$|kPcnlppZ6Xff~;<=?=e:kmwqYwayogeck ioqw[hskl`|$|kPcnlppZ6Xff~;<=?>269jjvrXx`zn`d`j/hlppZkrdmc}#}|j_bmmwqY6W98>7d`|t^rjt`jnfl%bb~zPmtngms)wzlUxy`Qyle00?lht|Vzb|hbfnd-jjvrXe|foe{!}erwop969:=1bb~zPphrfhlhb'`dxxRczleku+wct}e~7==0=4:kmwqYwayogeck ioqw[hskl`|$~h}zlu>25;433`dxxR~fpdnjj`)nfz~Taxbkiw-qavsk|5;92?:4ioqw[uowmecei"gasu]nqibn~&xnxb{<01=61=nfz~T|d~jlhlf+lht|Vg~`igy/sgpqir;9=4986gasu]smuckago$ec}{_lwo`lp(zly~`y2>5?07?lht|Vzb|hbfnd-jjvrXe|foe{!}erwop9716;>0ec}{_qksaioim&ceyQbumfjr*tb{|f0<91259jjvrXx`zn`d`j/hlppZkrdmc}#k|umv?5=85<2ceyQiqgomkc(agyS`{cdht,v`urd}6:53<<;hlppZvnxlfbbh!fnrv\ipjca%yi~{ct=3=61=nfz~T|d~jlhlf+lht|Vg~`igy/sgpqir;:94986gasu]smuckago$ec}{_lwo`lp(zly~`y2=1?07?lht|Vzb|hbfnd-jjvrXe|foe{!}erwop9456;>0ec}{_qksaioim&ceyQbumfjr*tb{|f0?=1259jjvrXx`zn`d`j/hlppZkrdmc}#k|umv?6185<2ceyQiqgomkc(agyS`{cdht,v`urd}6993<;;hlppZvnxlfbbh!fnrv\ipjca%yi~{ct=05:7295fnrv\tlvbd`dn#d`|t^ovhaoq'{oxyaz329<10>oi{}U{e}kciog,mkusWdghdx rdqvhq:517887d`|t^rjt`jnfl%bb~zPmtngms)umzgx1<1259jjvrXx`zn`d`j/hlppZkrdmc}#k|umv?7585<2ceyQiqgomkc(agyS`{cdht,v`urd}68=3<;;hlppZvnxlfbbh!fnrv\ipjca%yi~{ct=11:7295fnrv\tlvbd`dn#d`|t^ovhaoq'{oxyaz335<10>oi{}U{e}kciog,mkusWdghdx rdqvhq:4=78?7d`|t^rjt`jnfl%bb~zPmtngms)umzgx1=9>368mkusWyc{iagae.kmwqYj}enbz"|jstnw8619:=1bb~zPphrfhlhb'`dxxRczleku+wct}e~7?50=4:kmwqYwayogeck ioqw[hskl`|$~h}zlu>0=;443`dxxR~fpdnjj`)nfz~Taxbkiw-qavsk|595>95fnrv\tlvbd`dn#d`|t^ovhaoq'{oxyaz341<10>oi{}U{e}kciog,mkusWdghdx rdqvhq:3978?7d`|t^rjt`jnfl%bb~zPmtngms)umzgx1:=>368mkusWyc{iagae.kmwqYj}enbz"|jstnw8159:=1bb~zPphrfhlhb'`dxxRczleku+wct}e~7890=4:kmwqYwayogeck ioqw[hskl`|$~h}zlu>71;433`dxxR~fpdnjj`)nfz~Taxbkiw-qavsk|5>=2?:4ioqw[uowmecei"gasu]nqibn~&xnxb{<55=61=nfz~T|d~jlhlf+lht|Vg~`igy/sgpqir;<14986gasu]smuckago$ec}{_lwo`lp(zly~`y2;9?00?lht|Vzb|hbfnd-jjvrXe|foe{!}erwop929:=1bb~zPphrfhlhb'`dxxRczleku+wct}e~79=0=4:kmwqYwayogeck ioqw[hskl`|$~h}zlu>65;433`dxxR~fpdnjj`)nfz~Taxbkiw-qavsk|5?92?:4ioqw[uowmecei"gasu]nqibn~&xnxb{<41=61=nfz~T|d~jlhlf+lht|Vg~`igy/sgpqir;==4986gasu]smuckago$ec}{_lwo`lp(zly~`y2:5?07?lht|Vzb|hbfnd-jjvrXe|foe{!}erwop9316;>0ec}{_qksaioim&ceyQbumfjr*tb{|f0891259jjvrXx`zn`d`j/hlppZkrdmc}#k|umv?1=85<2ceyQiqgomkc(agyS`{cdht,v`urd}6>53<<;hlppZvnxlfbbh!fnrv\ipjca%yi~{ct=7=61=nfz~T|d~jlhlf+lht|Vg~`igy/sgpqir;>94986gasu]smuckago$ec}{_lwo`lp(zly~`y291?07?lht|Vzb|hbfnd-jjvrXe|foe{!}erwop9056;>0ec}{_qksaioim&ceyQbumfjr*tb{|f0;=1229jjvrXx`zn`d`j/hlppZkrdmc}#k|umv?2;443`dxxR~fpdnjj`)nfz~Taxbkiw-qavsk|5=5>>5fnrv\tlvbd`dn#d`|t^ovhaoq'{oxyaz38?00?lht|Vzb|hbfnd-jjvrXe|foe{!}erwop9?9:;1bb~zPphrfhlhb'`dxxRczleku+wct}e~TPmtz345451;i0ec}{_qksaioim&ceyQbumfjr*tb{|fS=Qbuy234732:l1bb~zPphrfhlhb'`dxxRczleku+wct}e~Toi{}U{e}kciog,mkusWdghdx rdqvhqY68Vg~t=>?23;1`>oi{}U{e}kciog,mkusWdghdx rdqvhqY68Vg~t=>?2471b>oi{}U{e}kciog,mkusWdghdx rdqvhqY68Vg~t=>?247\B7`1^ov|567:;39h6gasu]smuckago$ec}{_lwo`lp(zly~`yQ>1^ov|567:1^ov|567:9RI=3:kmwqYwayogeck ioqw[hskl`|$~h}zlu]267doi{}U{e}kciog,mkusWdghdx rdqvhqY6:Vg~t=>?23;1`>oi{}U{e}kciog,mkusWdghdx rdqvhqY6:Vg~t=>?2471b>oi{}U{e}kciog,mkusWdghdx rdqvhqY6:Vg~t=>?247\B7`3^ov|567:;39h6gasu]smuckago$ec}{_lwo`lp(zly~`yQ>3^ov|567:3^ov|567:9RI=3:kmwqYwayogeck ioqw[hskl`|$~h}zlu]207dTaxv?0101`>oi{}U{e}kciog,mkusWdghdx rdqvhqY6?23;1`>oi{}U{e}kciog,mkusWdghdx rdqvhqY6?2471b>oi{}U{e}kciog,mkusWdghdx rdqvhqY6?247\B7`Taxv?01061ZA5;2ceyQiqgomkc(agyS`{cdht,v`urd}U:9?l4ioqw[uowmecei"gasu]nqibn~&xnxb{_07\ip~78989h6gasu]smuckago$ec}{_lwo`lp(zly~`yQ>5^ov|567:;39h6gasu]smuckago$ec}{_lwo`lp(zly~`yQ>5^ov|567:5^ov|567:9RI=3:kmwqYwayogeck ioqw[hskl`|$~h}zlu]227doi{}U{e}kciog,mkusWdghdx rdqvhqY6>Vg~t=>?23;1`>oi{}U{e}kciog,mkusWdghdx rdqvhqY6>Vg~t=>?2471b>oi{}U{e}kciog,mkusWdghdx rdqvhqY6>Vg~t=>?247\B7`7^ov|567:;39h6gasu]smuckago$ec}{_lwo`lp(zly~`yQ>7^ov|567:7^ov|567:9RI=3:kmwqYwayogeck ioqw[hskl`|$~h}zlu]2<7doi{}U{e}kciog,mkusWdghdx rdqvhqY60Vg~t=>?23;1`>oi{}U{e}kciog,mkusWdghdx rdqvhqY60Vg~t=>?2471b>oi{}U{e}kciog,mkusWdghdx rdqvhqY60Vg~t=>?247\B7`9^ov|567:;39h6gasu]smuckago$ec}{_lwo`lp(zly~`yQ>9^ov|567:9^ov|567:9RI=a:kmwqYwayogeck ioqw[hskl`|$~h}zlu]2[hs89:9>n5fnrv\tlvbd`dn#d`|t^ovhaoq'{oxyazP1^ov|567:;39o6gasu]smuckago$ec}{_lwo`lp(zly~`yQ>_lw{4565=<8n7d`|t^rjt`jnfl%bb~zPmtngms)umzgxR?Pmtz34542=VL9i6gasu]smuckago$ec}{_lwo`lp(zly~`yQ>_lw{4565=